<!DOCTYPE html>
<html lang=zh>
<head>
    <meta charset="utf-8">
    
    <title>LErry</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
    <meta name="description" content="记录生活点滴">
<meta property="og:type" content="website">
<meta property="og:title" content="LErry">
<meta property="og:url" content="https://www.itchina.top/page/2/index.html">
<meta property="og:site_name" content="LErry">
<meta property="og:description" content="记录生活点滴">
<meta property="og:locale" content="zh-CN">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="LErry">
<meta name="twitter:description" content="记录生活点滴">
    

    
        <link rel="alternate" href="/atom.xml" title="LErry" type="application/atom+xml" />
    

    
        <link rel="icon" href="/css/images/shortcut_icon.png" />
    

    <link rel="stylesheet" href="/libs/font-awesome/css/font-awesome.min.css">
    <link rel="stylesheet" href="/libs/open-sans/styles.css">
    <link rel="stylesheet" href="/libs/source-code-pro/styles.css">

    <link rel="stylesheet" href="/css/style.css">

    <script src="/libs/jquery/2.1.3/jquery.min.js"></script>
    
    
        <link rel="stylesheet" href="/libs/lightgallery/css/lightgallery.min.css">
    
    
        <link rel="stylesheet" href="/libs/justified-gallery/justifiedGallery.min.css">
    
    
    
    


</head>

<body>
    <div id="container">
        <header id="header">
    <div id="header-main" class="header-inner">
        <div class="outer">
            <a href="/" id="logo">
                <i class="logo"></i>
                <span class="site-title">LErry</span>
            </a>
            <nav id="main-nav">
                
                    <a class="main-nav-link" href="/.">主页</a>
                
                    <a class="main-nav-link" href="/freebooks">书籍</a>
                
                    <a class="main-nav-link" href="/tags">标签</a>
                
                    <a class="main-nav-link" href="/archives">归档</a>
                
                    <a class="main-nav-link" href="/aboutme">关于</a>
                
            </nav>
            
                
                <nav id="sub-nav">
                    <div class="profile" id="profile-nav">
                        <a id="profile-anchor" href="javascript:;">
                            <img class="avatar" src="/css/images/avatar.png" />
                            <i class="fa fa-caret-down"></i>
                        </a>
                    </div>
                </nav>
            
            <div id="search-form-wrap">

    <form class="search-form">
        <input type="text" class="ins-search-input search-form-input" placeholder="搜索" />
        <button type="submit" class="search-form-submit"></button>
    </form>
    <div class="ins-search">
    <div class="ins-search-mask"></div>
    <div class="ins-search-container">
        <div class="ins-input-wrapper">
            <input type="text" class="ins-search-input" placeholder="想要查找什么..." />
            <span class="ins-close ins-selectable"><i class="fa fa-times-circle"></i></span>
        </div>
        <div class="ins-section-wrapper">
            <div class="ins-section-container"></div>
        </div>
    </div>
</div>
<script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: '文章',
            PAGES: '页面',
            CATEGORIES: '分类',
            TAGS: '标签',
            UNTITLED: '(未命名)',
        },
        ROOT_URL: '/',
        CONTENT_URL: '/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>
<script src="/js/insight.js"></script>

</div>
        </div>
    </div>
    <div id="main-nav-mobile" class="header-sub header-inner">
        <table class="menu outer">
            <tr>
                
                    <td><a class="main-nav-link" href="/.">主页</a></td>
                
                    <td><a class="main-nav-link" href="/freebooks">书籍</a></td>
                
                    <td><a class="main-nav-link" href="/tags">标签</a></td>
                
                    <td><a class="main-nav-link" href="/archives">归档</a></td>
                
                    <td><a class="main-nav-link" href="/aboutme">关于</a></td>
                
                <td>
                    
    <div class="search-form">
        <input type="text" class="ins-search-input search-form-input" placeholder="搜索" />
    </div>

                </td>
            </tr>
        </table>
    </div>
</header>

        <div class="outer">
            
                

<aside id="profile">
    <div class="inner profile-inner">
        <div class="base-info profile-block">
            <img id="avatar" src="/css/images/avatar.png" />
            <h2 id="name">LErry Li</h2>
            <h3 id="title">知我者谓我心忧，不知我者谓我何求</h3>
            <span id="location"><i class="fa fa-map-marker"></i>Shanghai, China</span>
            <a id="follow" target="_blank" href="https://github.com/lerry903">关注我</a>
        </div>
        <div class="article-info profile-block">
            <div class="article-info-block">
                65
                <span>文章</span>
            </div>
            <div class="article-info-block">
                54
                <span>标签</span>
            </div>
        </div>
        
        <div class="profile-block social-links">
            <table>
                <tr>
                    
                    
                    <td>
                        <a href="https://github.com/lerry903" target="_blank" title="github" class=tooltip>
                            <i class="fa fa-github"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="mailto:lerryli@foxmail.com" target="_blank" title="envelope" class=tooltip>
                            <i class="fa fa-envelope"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="http://wpa.qq.com/msgrd?v=3&uin=824444270&site=qq&menu=yes" target="_blank" title="qq" class=tooltip>
                            <i class="fa fa-qq"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="https://weibo.com/5941010376" target="_blank" title="weibo" class=tooltip>
                            <i class="fa fa-weibo"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/atom.xml" target="_blank" title="rss" class=tooltip>
                            <i class="fa fa-rss"></i>
                        </a>
                    </td>
                    
                </tr>
            </table>
        </div>
        
    </div>
</aside>

            
            <section id="main">
    <article id="post-Spring Boot 事务的使用" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2018/04/20/Spring Boot 事务的使用/">Spring Boot 事务的使用</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2018/04/20/Spring Boot 事务的使用/">
            <time datetime="2018-04-19T16:34:21.442Z" itemprop="datePublished">2018-04-20</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring/">Spring</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/spring/">spring</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p>Spring Boot 使用事务非常简单，首先使用注解 @EnableTransactionManagement 开启事务支持后，然后在访问 <a href="http://lib.csdn.net/base/14" target="_blank" rel="noopener"> 数据库
</a> 的Service方法上添加注解 @Transactional 便可。</p>
<p>关于事务管理器，不管是JPA还是JDBC等都实现自接口 PlatformTransactionManager 如果你添加的是 spring-boot-<br>starter-jdbc 依赖，框架会默认注入 DataSourceTransactionManager 实例。如果你添加的是 spring-boot-<br>starter-data-jpa 依赖，框架会默认注入 JpaTransactionManager 实例。</p>
<p>你可以在启动类中添加如下方法，Debug测试，就能知道自动注入的是 PlatformTransactionManager 接口的哪个实现类。</p>
<pre><code>@EnableTransactionManagement // 启注解事务管理，等同于xml配置方式的 &lt;tx:annotation-driven /&gt;
@SpringBootApplication
public class ProfiledemoApplication {

    @Bean
    public Object testBean(PlatformTransactionManager platformTransactionManager){
        System.out.println(&quot;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&quot; + platformTransactionManager.getClass().getName());
        return new Object();
    }

    public static void main(String[] args) {
        SpringApplication.run(ProfiledemoApplication.class, args);
    }
}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
</ul>
<p>这些SpringBoot为我们自动做了，这些对我们并不透明，如果你项目做的比较大，添加的持久化依赖比较多，我们还是会选择人为的指定使用哪个事务管理器。<br>代码如下：</p>
<pre><code>@EnableTransactionManagement
@SpringBootApplication
public class ProfiledemoApplication {

    // 其中 dataSource 框架会自动为我们注入
    @Bean
    public PlatformTransactionManager txManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public Object testBean(PlatformTransactionManager platformTransactionManager) {
        System.out.println(&quot;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&quot; + platformTransactionManager.getClass().getName());
        return new Object();
    }

    public static void main(String[] args) {
        SpringApplication.run(ProfiledemoApplication.class, args);
    }
}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
</ul>
<p>在Spring容器中，我们手工注解@Bean 将被优先加载，框架不会重新实例化其他的 PlatformTransactionManager 实现类。</p>
<p>然后在Service中，被 @Transactional 注解的方法，将支持事务。如果注解在类上，则整个类的所有方法都默认支持事务。</p>
<p>对于同一个工程中存在多个事务管理器要怎么处理，请看下面的实例，具体说明请看代码中的注释。</p>
<pre><code>@EnableTransactionManagement // 开启注解事务管理，等同于xml配置文件中的 &lt;tx:annotation-driven /&gt;
@SpringBootApplication
public class ProfiledemoApplication implements TransactionManagementConfigurer {

    @Resource(name=&quot;txManager2&quot;)
    private PlatformTransactionManager txManager2;

    // 创建事务管理器1
    @Bean(name = &quot;txManager1&quot;)
    public PlatformTransactionManager txManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    // 创建事务管理器2
    @Bean(name = &quot;txManager2&quot;)
    public PlatformTransactionManager txManager2(EntityManagerFactory factory) {
        return new JpaTransactionManager(factory);
    }

    // 实现接口 TransactionManagementConfigurer 方法，其返回值代表在拥有多个事务管理器的情况下默认使用的事务管理器
    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return txManager2;
    }

    public static void main(String[] args) {
        SpringApplication.run(ProfiledemoApplication.class, args);
    }

}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
</ul>
<pre><code>@Component
public class DevSendMessage implements SendMessage {

    // 使用value具体指定使用哪个事务管理器
    @Transactional(value=&quot;txManager1&quot;)
    @Override
    public void send() {
        System.out.println(&quot;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;Dev Send()&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&quot;);
        send2();
    }

    // 在存在多个事务管理器的情况下，如果使用value具体指定
    // 则默认使用方法 annotationDrivenTransactionManager() 返回的事务管理器
    @Transactional
    public void send2() {
        System.out.println(&quot;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;Dev Send2()&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&quot;);
    }

}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
</ul>
<p>注：<br>如果Spring容器中存在多个 PlatformTransactionManager 实例，并且没有实现接口<br>TransactionManagementConfigurer 指定默认值，在我们在方法上使用注解 @Transactional<br>的时候，就必须要用value指定，如果不指定，则会抛出异常。</p>
<p>对于系统需要提供默认事务管理的情况下，实现接口 TransactionManagementConfigurer 指定。</p>
<p>对有的系统，为了避免不必要的问题，在业务中必须要明确指定 @Transactional 的 value 值的情况下。不建议实现接口<br>TransactionManagementConfigurer，这样控制台会明确抛出异常，开发人员就不会忘记主动指定。</p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">


    <div class="bdsharebuttonbox">
    <a href="#" class="bds_more" data-cmd="more">分享到：</a>
    <a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间">QQ空间</a>
    <a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博">新浪微博</a>
    <a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博">腾讯微博</a>
    <a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网">人人网</a>
    <a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信">微信</a>
</div>
<script>
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{"bdSize":16}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
</script>
<style>
    .bdshare_popup_box {
        border-radius: 4px;
        border: #e1e1e1 solid 1px;
    }
    .bdshare-button-style0-16 a,
    .bdshare-button-style0-16 .bds_more {
        padding-left: 20px;
        margin: 6px 10px 6px 0;
    }
    .bdshare_dialog_list a,
    .bdshare_popup_list a,
    .bdshare_popup_bottom a {
        font-family: 'Microsoft Yahei';
    }
    .bdshare_popup_top {
        display: none;
    }
    .bdshare_popup_bottom {
        height: auto;
        padding: 5px;
    }
</style>


</div>

            
    
        <a href="https://www.itchina.top/2018/04/20/Spring Boot 事务的使用/#comments" id="sourceId::2018/04/20/Spring Boot 事务的使用/" class="article-comment-link cy_cmt_count">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring boot 使用Druid数据源" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2018/04/20/Spring boot 使用Druid数据源/">Spring boot 使用Druid数据源</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2018/04/20/Spring boot 使用Druid数据源/">
            <time datetime="2018-04-19T16:34:21.442Z" itemprop="datePublished">2018-04-20</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/J2EE/">J2EE</a><i class="fa fa-angle-right"></i><a class="article-category-link" href="/categories/J2EE/Spring/">Spring</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/Druid/">Druid</a>, <a class="tag-link" href="/tags/Spring-Boot/">Spring Boot</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p>Druid  为监控而生的数据库连接池  </p>
<p>由于工作需要，最近一个项目是Spring Boot架构的需要使用Druid作为数据源，所以整理了这样一篇文章</p>
<p>废话不多说，现在开始表演。</p>
<p>Druid Spring Boot Starter 用于在Spring Boot项目中轻松集成Druid数据库连接池和监控。  </p>
<h2 id="如何使用"><a href="#如何使用" class="headerlink" title="如何使用"></a>如何使用</h2><ol>
<li><p>在 Spring Boot 项目中加入 <code>druid-spring-boot-starter</code> 依赖 </p>
<p>   maven:</p>
<dependency><br>  <groupid>com.alibaba</groupid><br>  <artifactid>druid-spring-boot-starter</artifactid><br>  <version>1.1.6</version><br></dependency>

<p>   Gradle:<br>compile ‘com.alibaba:druid-spring-boot-starter:1.1.6’</p>
</li>
<li><p>添加配置 </p>
<p>   spring.datasource.url=<br>spring.datasource.username=<br>spring.datasource.password=<br>#其他配置（可选，不是必须的)</p>
</li>
</ol>
<h2 id="配置属性"><a href="#配置属性" class="headerlink" title="配置属性"></a>配置属性</h2><p>Druid Spring Boot Starter 配置属性的名称完全遵照 Druid，你可以通过 Spring Boot<br>配置文件来配置Druid数据库连接池和监控，如果没有配置则使用默认值。</p>
<pre><code>    JDBC 配置
spring.datasource.druid.url= # 或spring.datasource.url= 
spring.datasource.druid.username= # 或spring.datasource.username=
spring.datasource.druid.password= # 或spring.datasource.password=
spring.datasource.druid.driver-class-name= #或 spring.datasource.driver-class-name=

    连接池配置
spring.datasource.druid.initial-size=
spring.datasource.druid.max-active=
spring.datasource.druid.min-idle=
spring.datasource.druid.max-wait=
spring.datasource.druid.pool-prepared-statements=
spring.datasource.druid.max-pool-prepared-statement-per-connection-size= 
spring.datasource.druid.max-open-prepared-statements= #和上面的等价
spring.datasource.druid.validation-query=
spring.datasource.druid.validation-query-timeout=
spring.datasource.druid.test-on-borrow=
spring.datasource.druid.test-on-return=
spring.datasource.druid.test-while-idle=
spring.datasource.druid.time-between-eviction-runs-millis=
spring.datasource.druid.min-evictable-idle-time-millis=
spring.datasource.druid.max-evictable-idle-time-millis=
spring.datasource.druid.filters= #配置多个英文逗号分隔


    监控配置
# WebStatFilter配置，说明请参考Druid Wiki，配置_配置WebStatFilter
spring.datasource.druid.web-stat-filter.enabled= #是否启用StatFilter默认值true
spring.datasource.druid.web-stat-filter.url-pattern=
spring.datasource.druid.web-stat-filter.exclusions=
spring.datasource.druid.web-stat-filter.session-stat-enable=
spring.datasource.druid.web-stat-filter.session-stat-max-count=
spring.datasource.druid.web-stat-filter.principal-session-name=
spring.datasource.druid.web-stat-filter.principal-cookie-name=
spring.datasource.druid.web-stat-filter.profile-enable=

# StatViewServlet配置，说明请参考Druid Wiki，配置_StatViewServlet配置
spring.datasource.druid.stat-view-servlet.enabled= #是否启用StatViewServlet默认值true
spring.datasource.druid.stat-view-servlet.url-pattern=
spring.datasource.druid.stat-view-servlet.reset-enable=
spring.datasource.druid.stat-view-servlet.login-username=
spring.datasource.druid.stat-view-servlet.login-password=
spring.datasource.druid.stat-view-servlet.allow=
spring.datasource.druid.stat-view-servlet.deny=

# Spring监控配置，说明请参考Druid Github Wiki，配置_Druid和Spring关联监控配置
spring.datasource.druid.aop-patterns= # Spring监控AOP切入点，如x.y.z.service.*,配置多个英文逗号分隔
# 如果spring.datasource.druid.aop-patterns要代理的类没有定义interface请设置spring.aop.proxy-target-class=true
</code></pre><p>Druid Spring Boot Starter 不仅限于对以上配置属性提供支持，  <code>[ DruidDataSource ](https://gith
ub.com/alibaba/druid/blob/master/src/main/java/com/alibaba/druid/pool/DruidDat
aSource.java)</code> 内提供  <code>setter</code><br>方法的可配置属性都将被支持。你可以参考WIKI文档或通过IDE输入提示来进行配置。配置文件的格式你可以选择  <code>.properties</code> 或  <code>.yml</code> ，效果是一样的，在配置较多的情况下推荐使用  <code>.yml</code> 。</p>
<h2 id="如何配置多数据源"><a href="#如何配置多数据源" class="headerlink" title="如何配置多数据源"></a>如何配置多数据源</h2><ol>
<li><p>添加配置 </p>
<p>   spring.datasource.url=<br>spring.datasource.username=<br>spring.datasource.password=</p>
<h1 id="Druid-数据源配置，继承spring-datasource-配置，相同则覆盖"><a href="#Druid-数据源配置，继承spring-datasource-配置，相同则覆盖" class="headerlink" title="Druid 数据源配置，继承spring.datasource.* 配置，相同则覆盖"></a>Druid 数据源配置，继承spring.datasource.* 配置，相同则覆盖</h1><p>…<br>spring.datasource.druid.initial-size=5<br>spring.datasource.druid.max-active=5<br>…</p>
<h1 id="Druid-数据源-1-配置，继承spring-datasource-druid-配置，相同则覆盖"><a href="#Druid-数据源-1-配置，继承spring-datasource-druid-配置，相同则覆盖" class="headerlink" title="Druid 数据源 1 配置，继承spring.datasource.druid.* 配置，相同则覆盖"></a>Druid 数据源 1 配置，继承spring.datasource.druid.* 配置，相同则覆盖</h1><p>…<br>spring.datasource.druid.one.max-active=10<br>spring.datasource.druid.one.max-wait=10000<br>…</p>
<h1 id="Druid-数据源-2-配置，继承spring-datasource-druid-配置，相同则覆盖"><a href="#Druid-数据源-2-配置，继承spring-datasource-druid-配置，相同则覆盖" class="headerlink" title="Druid 数据源 2 配置，继承spring.datasource.druid.* 配置，相同则覆盖"></a>Druid 数据源 2 配置，继承spring.datasource.druid.* 配置，相同则覆盖</h1><p>…<br>spring.datasource.druid.two.max-active=20<br>spring.datasource.druid.two.max-wait=20000<br>…</p>
</li>
<li><p>创建数据源 </p>
<p>   @Primary<br>@Bean<br>@ConfigurationProperties(“spring.datasource.druid.one”)<br>public DataSource dataSourceOne(){<br>   return DruidDataSourceBuilder.create().build();<br>}<br>@Bean<br>@ConfigurationProperties(“spring.datasource.druid.two”)<br>public DataSource dataSourceTwo(){<br>   return DruidDataSourceBuilder.create().build();<br>}</p>
</li>
</ol>
<h2 id="如何配置-Filter"><a href="#如何配置-Filter" class="headerlink" title="如何配置 Filter"></a>如何配置 Filter</h2><p>你可以通过 <code>spring.datasource.druid.filters=stat,wall,log4j ...</code> 的方式来启用相应的内置Filte<br>r，不过这些Filter都是默认配置。如果默认配置不能满足你的需求，你可以放弃这种方式，通过配置文件来配置Filter，下面是例子。</p>
<pre><code>    # 配置StatFilter 
spring.datasource.druid.filter.stat.db-type=h2
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=2000

# 配置WallFilter 
spring.datasource.druid.filter.wall.enabled=true
spring.datasource.druid.filter.wall.db-type=h2
spring.datasource.druid.filter.wall.config.delete-allow=false
spring.datasource.druid.filter.wall.config.drop-table-allow=false
</code></pre><p>目前为以下 Filter 提供了配置支持，请参考文档或者根据IDE提示（ <code>spring.datasource.druid.filter.*</code><br>）进行配置。</p>
<pre><code>* StatFilter 
* WallFilter 
* ConfigFilter 
* EncodingConvertFilter 
* Slf4jLogFilter 
* Log4jFilter 
* Log4j2Filter 
* CommonsLogFilter 
</code></pre><p>要想使自定义 Filter 配置生效需要将对应 Filter 的 <code>enabled</code> 设置为 <code>true</code> ，Druid Spring Boot<br>Starter 默认会启用 StatFilter，你也可以将其 <code>enabled</code> 设置为 <code>false</code> 来禁用它。</p>
<p>参考文档：</p>
<p><a href="https://github.com/alibaba/druid/wiki/%E9%A6%96%E9%A1%B5" target="_blank" rel="noopener"> Druid Wiki </a></p>
<p><a href="http://docs.spring.io/spring-
boot/docs/current/reference/htmlsingle/" target="_blank" rel="noopener"> Spring Boot Reference </a></p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">


    <div class="bdsharebuttonbox">
    <a href="#" class="bds_more" data-cmd="more">分享到：</a>
    <a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间">QQ空间</a>
    <a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博">新浪微博</a>
    <a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博">腾讯微博</a>
    <a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网">人人网</a>
    <a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信">微信</a>
</div>
<script>
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{"bdSize":16}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
</script>
<style>
    .bdshare_popup_box {
        border-radius: 4px;
        border: #e1e1e1 solid 1px;
    }
    .bdshare-button-style0-16 a,
    .bdshare-button-style0-16 .bds_more {
        padding-left: 20px;
        margin: 6px 10px 6px 0;
    }
    .bdshare_dialog_list a,
    .bdshare_popup_list a,
    .bdshare_popup_bottom a {
        font-family: 'Microsoft Yahei';
    }
    .bdshare_popup_top {
        display: none;
    }
    .bdshare_popup_bottom {
        height: auto;
        padding: 5px;
    }
</style>


</div>

            
    
        <a href="https://www.itchina.top/2018/04/20/Spring boot 使用Druid数据源/#comments" id="sourceId::2018/04/20/Spring boot 使用Druid数据源/" class="article-comment-link cy_cmt_count">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot 入门" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2018/04/20/Spring Boot 入门/">Spring Boot 入门</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2018/04/20/Spring Boot 入门/">
            <time datetime="2018-04-19T16:34:21.441Z" itemprop="datePublished">2018-04-20</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring/">Spring</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/spring/">spring</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p>一、简介</p>
<p>Spring 官方网站本身使用Spring 框架开发，随着功能以及业务逻辑的日益复杂，应用伴随着大量的XML配置文件以及复杂的Bean依赖关系。<br>随着Spring 3.0的发布，Spring IO团队主键开始摆脱XML配置文件，并且在开发过程中大量使用“约定优先配置”（convention over<br>configuration）的思想来摆脱Spring框架中各种复杂的配置，衍生了 <a href="http://lib.csdn.net/base/17" target="_blank" rel="noopener"> Java </a><br>Config。</p>
<p>Spring Boot正是在这样的一个背景下被抽象出来的开发框架，它本身并不提供Spring框架的核心特性以及扩展功能，只是用于快速、敏捷地开发新一代基于S<br>pring框架的应用程序。也就是说，它并不是用来替代Spring的解决方案，而是和Spring框架紧密结合用于提升Spring开发者体验的工具。同时它集成了<br>大量常用的第三方库配置（例如Jackson, JDBC, Mongo, Redis, Mail等等），Spring<br>Boot应用中这些第三方库几乎可以零配置的开箱即用（out-of-the-box），大部分的Spring<br>Boot应用都只需要非常少量的配置代码，开发者能够更加专注于业务逻辑。</p>
<p>该项目旨在帮助开发者更容易地创建基于Spring的应用程序和服务，使得现有的和新的Spring开发者能够最快速地获得所需要的Spring功能。</p>
<p>Spring Boot不生成代码，且完全不需要XML配置。其主要目标如下：<br>- 为所有的Spring开发工作提供一个更快、更广泛的入门经验。<br>- 开箱即用，你也可以通过修改默认值来快速满足你的项目的需求。<br>- 提供了一系列大型项目中常见的非功能性特性，如嵌入式服务器、安全、指标，健康检测、外部配置等。</p>
<p>博主准备写一组 Spring-Boot 入门的帖子，仅为了抛砖引玉，让需要的同学可以尽快了解如何使用Spring-Boot，内容参考官网和网上的资料（ <a href="http://projects.spring.io/spring-
boot/" target="_blank" rel="noopener"><br>http://projects.spring.io/spring-boot/ </a> ）。</p>
<hr>
<p>开发工具：Spring Tool Suite v_3.7.2（简称STS）<br>官网地址： <a href="http://spring.io/tools/sts" target="_blank" rel="noopener"> http://spring.io/tools/sts </a></p>
<p>二、入门实例 - HelloWorld</p>
<p>File &gt; New &gt; Spring Starter Project<br><img src="https://img-blog.csdn.net/20160112091624877" alt="这里写图片描述"><br><img src="https://img-blog.csdn.net/20160112091636862" alt="这里写图片描述"></p>
<p>Next &gt; Finish</p>
<p>项目创建完成：<br><img src="https://img-blog.csdn.net/20160112091650587" alt="这里写图片描述"></p>
<p>可以看出，项目源码就一个Java类，在pom.xml中有spring-boot-starter-web的依赖。</p>
<p>SpringBootSampleApplication.java</p>
<pre><code>package org.springboot.sample;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootSampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootSampleApplication.class, args);
    }
}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
</ul>
<p>pom.xml</p>
<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;

    &lt;groupId&gt;org.springboot.sample&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-sample&lt;/artifactId&gt;
    &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
    &lt;packaging&gt;jar&lt;/packaging&gt;

    &lt;name&gt;spring-boot-sample&lt;/name&gt;
    &lt;description&gt;Spring Boot Sample Web Application&lt;/description&gt;

    &lt;parent&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
        &lt;version&gt;1.3.1.RELEASE&lt;/version&gt;
        &lt;relativePath/&gt; &lt;!-- lookup parent from repository --&gt;
    &lt;/parent&gt;

    &lt;properties&gt;
        &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
        &lt;java.version&gt;1.8&lt;/java.version&gt;
    &lt;/properties&gt;

    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
        &lt;/dependency&gt;

        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
            &lt;scope&gt;test&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;

    &lt;build&gt;
        &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;


&lt;/project&gt;
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
<li>40 </li>
<li>41 </li>
<li>42 </li>
<li>43 </li>
<li>44 </li>
<li>45 </li>
<li>46 </li>
<li>47 </li>
<li>48 </li>
<li>49 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
<li>40 </li>
<li>41 </li>
<li>42 </li>
<li>43 </li>
<li>44 </li>
<li>45 </li>
<li>46 </li>
<li>47 </li>
<li>48 </li>
<li>49 </li>
</ul>
<p>这样就完成了项目的创建，下面我们创建一个 HelloController.java 定义3个方法</p>
<pre><code>package org.springboot.sample.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(&quot;/hello&quot;)
public class HelloController {

    @RequestMapping
    public String hello() {
        return &quot;Hello Spring-Boot&quot;;
    }

    @RequestMapping(&quot;/info&quot;)
    public Map&lt;String, String&gt; getInfo(@RequestParam String name) {
        Map&lt;String, String&gt; map = new HashMap&lt;&gt;();
        map.put(&quot;name&quot;, name);
        return map;
    }

    @RequestMapping(&quot;/list&quot;)
    public List&lt;Map&lt;String, String&gt;&gt; getList() {
        List&lt;Map&lt;String, String&gt;&gt; list = new ArrayList&lt;&gt;();
        Map&lt;String, String&gt; map = null;
        for (int i = 1; i &lt;= 5; i++) {
            map = new HashMap&lt;&gt;();
            map.put(&quot;name&quot;, &quot;Shanhy-&quot; + i);
            list.add(map);
        }
        return list;
    }
}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
</ul>
<p>然后现在可以直接运行 SpringBootSampleApplication 的main方法，和执行普通java程序一样。<br>然后可以看到spring-boot 内置server容器（默认为Tomcat），这一切spring-boot 都帮我们做好了。</p>
<p>控制台输出内容 Started SpringBootSampleApplication in 7.358 seconds (JVM running for<br>9.154) 表示服务已经启动。</p>
<p>在浏览器输入我们3个请求便可看到结果。<br><a href="http://localhost:8080/hello" target="_blank" rel="noopener"> http://localhost:8080/hello </a><br>输出：Hello Spring-Boot<br><a href="http://localhost:8080/hello/info?name=shanhy" target="_blank" rel="noopener"> http://localhost:8080/hello/info?name=shanhy
</a><br>输出：{“name”:”shanhy”}<br><a href="http://localhost:8080/hello/list" target="_blank" rel="noopener"> http://localhost:8080/hello/list </a><br>输出：[{“name”:”Shanhy-1”},{“name”:”Shanhy-2”},{“name”:”Shanhy-3”},{“name”:”Shanh<br>y-4”},{“name”:”Shanhy-5”}]</p>
<p>通过我们的Hello实例，相信大家一目了然，可谓spring-boot创建一个项目如此简单，完全可以在几分钟内将服务启动。<br>spring-boot抛弃繁琐的配置，让开发人员更专注与业务逻辑的实现。后面几篇文章将会对spring-boot的多个方面通过实例的方式呈现给大家。</p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">


    <div class="bdsharebuttonbox">
    <a href="#" class="bds_more" data-cmd="more">分享到：</a>
    <a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间">QQ空间</a>
    <a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博">新浪微博</a>
    <a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博">腾讯微博</a>
    <a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网">人人网</a>
    <a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信">微信</a>
</div>
<script>
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{"bdSize":16}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
</script>
<style>
    .bdshare_popup_box {
        border-radius: 4px;
        border: #e1e1e1 solid 1px;
    }
    .bdshare-button-style0-16 a,
    .bdshare-button-style0-16 .bds_more {
        padding-left: 20px;
        margin: 6px 10px 6px 0;
    }
    .bdshare_dialog_list a,
    .bdshare_popup_list a,
    .bdshare_popup_bottom a {
        font-family: 'Microsoft Yahei';
    }
    .bdshare_popup_top {
        display: none;
    }
    .bdshare_popup_bottom {
        height: auto;
        padding: 5px;
    }
</style>


</div>

            
    
        <a href="https://www.itchina.top/2018/04/20/Spring Boot 入门/#comments" id="sourceId::2018/04/20/Spring Boot 入门/" class="article-comment-link cy_cmt_count">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot 日志记录 SLF4J" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2018/04/20/Spring Boot 日志记录 SLF4J/">Spring Boot 日志记录 SLF4J</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2018/04/20/Spring Boot 日志记录 SLF4J/">
            <time datetime="2018-04-19T16:34:21.440Z" itemprop="datePublished">2018-04-20</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring/">Spring</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/spring/">spring</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p>在开发中打印内容，使用 System.out.println() 和 Log4j 应当是人人皆知的方法了。<br>其实在开发中我们不建议使用 System.out 因为大量的使用 System.out 会增加资源的消耗。<br>而Log4j 更为灵活在性能上也相比 System.out 要高，我们可以配置输出级别，可以指定多个日志文件分别记录不同的日志。<br>使用 System.out 是在当前线程执行的，写入文件也是写入完毕后才继续执行下面的程序。而使用Log工具不但可以控制日志是否输出，怎么输出，它的处理机制<br>也是通知写日志，继续执行后面的代码不必等日志写完。<br>如非必要，建议大家不要使用控制台输出，因为控制台输出没有优先级会显得输出太乱。</p>
<p>个人推荐使用 SLF4J（Simple Logging Facade For <a href="http://lib.csdn.net/base/17" target="_blank" rel="noopener"> Java </a><br>）的logback来输出日志，其比log4j 要好，因为他效率更高。</p>
<p>Spring Boot 提供了一套日志系统，logback是最优先的选择。配置了logback.xml可以利用Spring Boot提供的默认日志配置：</p>
<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;configuration&gt;
    &lt;include resource=&quot;org/springframework/boot/logging/logback/base.xml&quot;/&gt;
    &lt;logger name=&quot;org.springframework.web&quot; level=&quot;DEBUG&quot;/&gt;
&lt;/configuration&gt;
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
</ul>
<p>这样就定义了一个 捕获 org.springframework.web 的日志，日志级别是 DEBUG，上面引用的base.xml 文件内容为：</p>
<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;

&lt;!--
Base logback configuration provided for compatibility with Spring Boot 1.1
--&gt;

&lt;included&gt;
    &lt;include resource=&quot;org/springframework/boot/logging/logback/defaults.xml&quot; /&gt;
    &lt;property name=&quot;LOG_FILE&quot; value=&quot;${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}&quot;/&gt;
    &lt;include resource=&quot;org/springframework/boot/logging/logback/console-appender.xml&quot; /&gt;
    &lt;include resource=&quot;org/springframework/boot/logging/logback/file-appender.xml&quot; /&gt;
    &lt;root level=&quot;INFO&quot;&gt;
        &lt;appender-ref ref=&quot;CONSOLE&quot; /&gt;
        &lt;appender-ref ref=&quot;FILE&quot; /&gt;
    &lt;/root&gt;
&lt;/included&gt;
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
</ul>
<p>Spring Boot的日志系统预先定义了一些系统变量：</p>
<p>P  I  D  ，  当  前  进  程  I  D  {PID}，当前进程ID {LOG_FILE}，Spring<br>Boot配置文件（application.properties|.yml）中logging.file的值<br>${LOG_PATH}, Spring Boot配置文件中logging.path的值<br>同时默认情况下包含另个appender——一个是控制台，一个是文件，分别定义在console-appender.xml和file-<br>appender.xml中。同时对于应用的日志级别也可以通过application.properties进行定义：</p>
<pre><code>logging.level.org.springframework.web=DEBUG
logging.level.org.springboot.sample=TRACE
</code></pre><ul>
<li>1 </li>
<li>2 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
</ul>
<p>这样相当于我们在logback.xml 中配置的对应的日志级别。名称以logging.level开头，后面跟要输入日志的包名。</p>
<p>_ <em> 如果在 logback.xml 和 application.properties 中定义了相同的配置（如都配置了<br>org.springframework.web）但是输出级别不同，则实际上 application.properties 的优先级高于<br>logback.xml </em> _</p>
<p>我们既然使用了maven来管理项目，我们就可以根据不同环境来定义不同的日志输出，在 logback-spring.xml 中使用 springProfile<br>节点来定义，方法如下：<br>注意文件名称不是logback.xml，想使用spring扩展profile支持，要以logback-spring.xml命名</p>
<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;configuration&gt;
    &lt;include resource=&quot;org/springframework/boot/logging/logback/base.xml&quot; /&gt;
    &lt;logger name=&quot;org.springframework.web&quot; level=&quot;INFO&quot;/&gt;
    &lt;logger name=&quot;org.springboot.sample&quot; level=&quot;TRACE&quot; /&gt;

    &lt;springProfile name=&quot;dev&quot;&gt;
        &lt;logger name=&quot;org.springboot.sample&quot; level=&quot;DEBUG&quot; /&gt;
    &lt;/springProfile&gt;

    &lt;springProfile name=&quot;staging&quot;&gt;
        &lt;logger name=&quot;org.springboot.sample&quot; level=&quot;INFO&quot; /&gt;
    &lt;/springProfile&gt;

&lt;/configuration&gt;
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
</ul>
<p>如上我们默认为 org.springboot.sample 定义了TRACE级别的输出，下面又定义两个 springProfile ，分别是 dev 和<br>staging，输出级别分别是 DEBUG 和 INFO<br>我们可以启动服务的时候指定 profile （如不指定使用默认），如指定staging 的方式为：</p>
<pre><code>java -jar myapp.jar --spring.profiles.active=staging
</code></pre><ul>
<li>1 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
</ul>
<p>下面介绍两种常用的Appender</p>
<h2 id="ConsoleAppender"><a href="#ConsoleAppender" class="headerlink" title="ConsoleAppender"></a>ConsoleAppender</h2><p>Logback使用appender来定义日志输出，在开发过程中最常用的是将日志输出到控制台：</p>
<pre><code>&lt;appender name=&quot;consoleAppender&quot; class=&quot;ch.qos.logback.core.ConsoleAppender&quot;&gt;
  &lt;encoder&gt;
    &lt;Pattern&gt;.%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %n&lt;/Pattern&gt;
  &lt;/encoder&gt;
  &lt;filter class=&quot;ch.qos.logback.classic.filter.ThresholdFilter&quot;&gt;
    &lt;level&gt;TRACE&lt;/level&gt;
  &lt;/filter&gt;
&lt;/appender&gt; 
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
</ul>
<p>表示对日志进行编码</p>
<ul>
<li>%d{HH:mm:ss.SSS}——日志输出时间 </li>
<li>%thread——输出日志的进程名字，这在Web应用以及异步任务处理中很有用 </li>
<li>%-5level——日志级别，并且使用5个字符靠左对齐 </li>
<li>%logger{36}——日志输出者的名字 </li>
<li>%msg——日志消息 </li>
<li>%n——平台的换行符 </li>
</ul>
<p>在这种格式下一条日志的输出结果如下：</p>
<pre><code>10:12:51.012 [threadName] DEBUG o.c.d.r.util.LoggingResponseFilter
</code></pre><ul>
<li>1 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
</ul>
<h2 id="RollingFileAppender"><a href="#RollingFileAppender" class="headerlink" title="RollingFileAppender"></a>RollingFileAppender</h2><p>另一种常见的日志输出到文件，随着应用的运行时间越来越长，日志也会增长的越来越多，将他们输出到同一个文件并非一个好办法。RollingFileAppender<br>用于切分文件日志：</p>
<pre><code> &lt;appender name=&quot;dailyRollingFileAppender&quot; class=&quot;ch.qos.logback.core.rolling.RollingFileAppender&quot;&gt;
  &lt;File&gt;/data/log/app.log&lt;/File&gt;
  &lt;rollingPolicy class=&quot;ch.qos.logback.core.rolling.TimeBasedRollingPolicy&quot;&gt;
    &lt;!-- daily rollover --&gt;
    &lt;FileNamePattern&gt;rest-demo.%d{yyyy-MM-dd}.log&lt;/FileNamePattern&gt;
    &lt;!-- keep 30 days&apos; worth of history --&gt;
    &lt;maxHistory&gt;30&lt;/maxHistory&gt;         
  &lt;/rollingPolicy&gt;
  &lt;encoder&gt;
    &lt;Pattern&gt;%d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg %n&lt;/Pattern&gt;
  &lt;/encoder&gt;        
&lt;/appender&gt;
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
</ul>
<p>其中重要的是rollingPolicy的定义，上例中rest-demo.%d{yyyy-MM-<br>dd}.log定义了日志的切分方式——把每一天的日志归档到一个文件中，30表示只保留最近30天的日志，以防止日志填满整个磁盘空间。同理，可以使用%d<br>{yyyy-MM-dd_HH-mm}来定义精确到分的日志切分方式。</p>
<h2 id="Sentry"><a href="#Sentry" class="headerlink" title="Sentry"></a>Sentry</h2><p>Sentry是一个统一的日志跟踪平台，在传统的日志管理中，都是在服务器上通过tail, vim等工具查看日志，并且不同的日志位置也个不相同，而Sentry则<br>是将这些日志（主要是错误日志）通过统一的接口收集起来，并且提供跟踪、管理的功能，使得应用程序的错误、Bug能够即时被解决。</p>
<p>Sentry提供了Java库——Raven<br>Java，Java应用程序能够在捕获异常后将其发送到Sentry服务器中，另一方面它包含了各类日志框架的支持，以Logbakc为例：</p>
<pre><code> &lt;dependency&gt;
    &lt;groupId&gt;net.kencochrane.raven&lt;/groupId&gt;
    &lt;artifactId&gt;raven-logback&lt;/artifactId&gt;
    &lt;version&gt;6.0.0&lt;/version&gt;
&lt;/dependency&gt;
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
</ul>
<p>在logback.xml中定义appender：</p>
<pre><code> &lt;configuration&gt;
    &lt;appender name=&quot;Sentry&quot; class=&quot;net.kencochrane.raven.logback.SentryAppender&quot;&gt;
        &lt;dsn&gt;https://publicKey:secretKey@host:port/1?options&lt;/dsn&gt;
        &lt;tags&gt;tag1:value1,tag2:value2&lt;/tags&gt;
        &lt;!-- Optional, allows to select the ravenFactory --&gt;
        &lt;!--&lt;ravenFactory&gt;net.kencochrane.raven.DefaultRavenFactory&lt;/ravenFactory&gt;--&gt;
    &lt;/appender&gt;
    &lt;root level=&quot;warn&quot;&gt;
        &lt;appender-ref ref=&quot;Sentry&quot;/&gt;
    &lt;/root&gt;
&lt;/configuration&gt;
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
</ul>
<p>我们推荐在这个中加入用于过滤 ERROR 级别的日志。</p>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>在Spring Boot 中记录日志只需两步：<br>1、在 src/main/resources 下面创建logback.xml 文件，并按上面讲述的进行配置。<br>或者使用最简单的方法在 application 配置文件中配置。<br>2、在Java代码中创建实例，并在需要输出日志的地方使用。</p>
<pre><code>// 在Java类中创建 logger 实例
private static final Logger logger = LoggerFactory.getLogger(SpringBootSampleApplication.class);
// 在方法中使用日志输出，如
public void logTest() {
    logger.debug(&quot;日志输出测试 Debug&quot;);
    logger.trace(&quot;日志输出测试 Trace&quot;);
    logger.info(&quot;日志输出测试 Info&quot;);
}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
</ul>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">


    <div class="bdsharebuttonbox">
    <a href="#" class="bds_more" data-cmd="more">分享到：</a>
    <a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间">QQ空间</a>
    <a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博">新浪微博</a>
    <a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博">腾讯微博</a>
    <a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网">人人网</a>
    <a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信">微信</a>
</div>
<script>
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{"bdSize":16}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
</script>
<style>
    .bdshare_popup_box {
        border-radius: 4px;
        border: #e1e1e1 solid 1px;
    }
    .bdshare-button-style0-16 a,
    .bdshare-button-style0-16 .bds_more {
        padding-left: 20px;
        margin: 6px 10px 6px 0;
    }
    .bdshare_dialog_list a,
    .bdshare_popup_list a,
    .bdshare_popup_bottom a {
        font-family: 'Microsoft Yahei';
    }
    .bdshare_popup_top {
        display: none;
    }
    .bdshare_popup_bottom {
        height: auto;
        padding: 5px;
    }
</style>


</div>

            
    
        <a href="https://www.itchina.top/2018/04/20/Spring Boot 日志记录 SLF4J/#comments" id="sourceId::2018/04/20/Spring Boot 日志记录 SLF4J/" class="article-comment-link cy_cmt_count">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot 启动加载数据 CommandLineRunner" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2018/04/20/Spring Boot 启动加载数据 CommandLineRunner/">Spring Boot 启动加载数据 CommandLineRunner</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2018/04/20/Spring Boot 启动加载数据 CommandLineRunner/">
            <time datetime="2018-04-19T16:34:21.440Z" itemprop="datePublished">2018-04-20</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring/">Spring</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/spring/">spring</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p>实际应用中，我们会有在项目服务启动的时候就去加载一些数据或做一些事情这样的需求。<br>为了解决这样的问题，Spring Boot 为我们提供了一个方法，通过实现接口 CommandLineRunner 来实现。</p>
<p>很简单，只需要一个类就可以，无需其他配置。<br>创建实现接口 CommandLineRunner 的类</p>
<pre><code>package org.springboot.sample.runner;

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

/**
 * 服务启动执行
 *
 * @author   单红宇(365384722)
 * @myblog  http://blog.csdn.net/catoop/
 * @create    2016年1月9日
 */
@Component
public class MyStartupRunner1 implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println(&quot;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;服务启动执行，执行加载数据等操作&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&quot;);
    }

}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
</ul>
<p>Spring Boot应用程序在启动后，会遍历CommandLineRunner接口的实例并运行它们的run方法。也可以利用@Order注解（或者实现Ord<br>er接口）来规定所有CommandLineRunner实例的运行顺序。</p>
<p>如下我们使用@Order 注解来定义执行顺序。</p>
<pre><code>package org.springboot.sample.runner;

import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 服务启动执行
 *
 * @author   单红宇(365384722)
 * @myblog  http://blog.csdn.net/catoop/
 * @create    2016年1月9日
 */
@Component
@Order(value=2)
public class MyStartupRunner1 implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println(&quot;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;服务启动执行，执行加载数据等操作 11111111 &lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&quot;);
    }

}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
</ul>
<pre><code>package org.springboot.sample.runner;

import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 服务启动执行
 *
 * @author   单红宇(365384722)
 * @myblog  http://blog.csdn.net/catoop/
 * @create    2016年1月9日
 */
@Component
@Order(value=1)
public class MyStartupRunner2 implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println(&quot;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;服务启动执行，执行加载数据等操作 22222222 &lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&quot;);
    }

}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
</ul>
<p>启动程序后，控制台输出结果为：</p>
<pre><code>&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;服务启动执行，执行加载数据等操作 22222222 &lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;服务启动执行，执行加载数据等操作 11111111 &lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;
</code></pre><ul>
<li>1 </li>
<li>2 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
</ul>
<p>根据控制台结果可判断，@Order 注解的执行优先级是按value值从小到大顺序。</p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">


    <div class="bdsharebuttonbox">
    <a href="#" class="bds_more" data-cmd="more">分享到：</a>
    <a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间">QQ空间</a>
    <a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博">新浪微博</a>
    <a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博">腾讯微博</a>
    <a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网">人人网</a>
    <a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信">微信</a>
</div>
<script>
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{"bdSize":16}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
</script>
<style>
    .bdshare_popup_box {
        border-radius: 4px;
        border: #e1e1e1 solid 1px;
    }
    .bdshare-button-style0-16 a,
    .bdshare-button-style0-16 .bds_more {
        padding-left: 20px;
        margin: 6px 10px 6px 0;
    }
    .bdshare_dialog_list a,
    .bdshare_popup_list a,
    .bdshare_popup_bottom a {
        font-family: 'Microsoft Yahei';
    }
    .bdshare_popup_top {
        display: none;
    }
    .bdshare_popup_bottom {
        height: auto;
        padding: 5px;
    }
</style>


</div>

            
    
        <a href="https://www.itchina.top/2018/04/20/Spring Boot 启动加载数据 CommandLineRunner/#comments" id="sourceId::2018/04/20/Spring Boot 启动加载数据 CommandLineRunner/" class="article-comment-link cy_cmt_count">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot 拦截器" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2018/04/20/Spring Boot 拦截器/">Spring Boot 拦截器</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2018/04/20/Spring Boot 拦截器/">
            <time datetime="2018-04-19T16:34:21.439Z" itemprop="datePublished">2018-04-20</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring/">Spring</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/spring/">spring</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p>上一篇对过滤器的定义做了说明，也比较简单。过滤器属于Servlet范畴的API，与Spring 没什么关系。<br>Web开发中，我们除了使用 Filter 来过滤请web求外，还可以使用Spring提供的HandlerInterceptor（拦截器）。</p>
<p>HandlerInterceptor 的功能跟过滤器类似，但是提供更精细的的控制能力：在request被响应之前、request被响应之后、视图渲染之前以及<br>request全部结束之后。我们不能通过拦截器修改request内容，但是可以通过抛出异常（或者返回false）来暂停request的执行。</p>
<p>实现 UserRoleAuthorizationInterceptor 的拦截器有：<br>ConversionServiceExposingInterceptor<br>CorsInterceptor<br>LocaleChangeInterceptor<br>PathExposingHandlerInterceptor<br>ResourceUrlProviderExposingInterceptor<br>ThemeChangeInterceptor<br>UriTemplateVariablesHandlerInterceptor<br>UserRoleAuthorizationInterceptor</p>
<p>其中 LocaleChangeInterceptor 和 ThemeChangeInterceptor 比较常用。</p>
<p>配置拦截器也很简单，Spring 为什么提供了基础类WebMvcConfigurerAdapter ，我们只需要重写 addInterceptors<br>方法添加注册拦截器。</p>
<p>实现自定义拦截器只需要3步：<br>1、创建我们自己的拦截器类并实现 HandlerInterceptor 接口。<br>2、创建一个 <a href="http://lib.csdn.net/base/17" target="_blank" rel="noopener"> Java </a> 类继承WebMvcConfigurerAdapter，并重写<br>addInterceptors 方法。<br>2、实例化我们自定义的拦截器，然后将对像手动添加到拦截器链中（在addInterceptors方法中添加）。<br>PS：本文重点在如何在Spring-Boot中使用拦截器，关于拦截器的原理请大家查阅资料了解。</p>
<p>代码示例：</p>
<p>MyInterceptor1.java</p>
<pre><code>package org.springboot.sample.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * 自定义拦截器1
 *
 * @author   单红宇(365384722)
 * @myblog  http://blog.csdn.net/catoop/
 * @create    2016年1月7日
 */
public class MyInterceptor1 implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println(&quot;&gt;&gt;&gt;MyInterceptor1&gt;&gt;&gt;&gt;&gt;&gt;&gt;在请求处理之前进行调用（Controller方法调用之前）&quot;);

        return true;// 只有返回true才会继续向下执行，返回false取消当前请求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println(&quot;&gt;&gt;&gt;MyInterceptor1&gt;&gt;&gt;&gt;&gt;&gt;&gt;请求处理之后进行调用，但是在视图被渲染之前（Controller方法调用之后）&quot;);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println(&quot;&gt;&gt;&gt;MyInterceptor1&gt;&gt;&gt;&gt;&gt;&gt;&gt;在整个请求结束之后被调用，也就是在DispatcherServlet 渲染了对应的视图之后执行（主要是用于进行资源清理工作）&quot;);
    }

}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
</ul>
<p>MyInterceptor2.java</p>
<pre><code>package org.springboot.sample.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * 自定义拦截器2
 *
 * @author   单红宇(365384722)
 * @myblog  http://blog.csdn.net/catoop/
 * @create    2016年1月7日
 */
public class MyInterceptor2 implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println(&quot;&gt;&gt;&gt;MyInterceptor2&gt;&gt;&gt;&gt;&gt;&gt;&gt;在请求处理之前进行调用（Controller方法调用之前）&quot;);

        return true;// 只有返回true才会继续向下执行，返回false取消当前请求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println(&quot;&gt;&gt;&gt;MyInterceptor2&gt;&gt;&gt;&gt;&gt;&gt;&gt;请求处理之后进行调用，但是在视图被渲染之前（Controller方法调用之后）&quot;);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println(&quot;&gt;&gt;&gt;MyInterceptor2&gt;&gt;&gt;&gt;&gt;&gt;&gt;在整个请求结束之后被调用，也就是在DispatcherServlet 渲染了对应的视图之后执行（主要是用于进行资源清理工作）&quot;);
    }

}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
</ul>
<p>MyWebAppConfigurer.java</p>
<pre><code>package org.springboot.sample.config;

import org.springboot.sample.interceptor.MyInterceptor1;
import org.springboot.sample.interceptor.MyInterceptor2;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MyWebAppConfigurer 
        extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 多个拦截器组成一个拦截器链
        // addPathPatterns 用于添加拦截规则
        // excludePathPatterns 用户排除拦截
        registry.addInterceptor(new MyInterceptor1()).addPathPatterns(&quot;/**&quot;);
        registry.addInterceptor(new MyInterceptor2()).addPathPatterns(&quot;/**&quot;);
        super.addInterceptors(registry);
    }

}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
</ul>
<p>然后在浏览器输入地址： <a href="http://localhost:8080/index" target="_blank" rel="noopener"> http://localhost:8080/index </a><br>后，控制台的输出为：</p>
<pre><code>&gt;&gt;&gt;MyInterceptor1&gt;&gt;&gt;&gt;&gt;&gt;&gt;在请求处理之前进行调用（Controller方法调用之前）
&gt;&gt;&gt;MyInterceptor2&gt;&gt;&gt;&gt;&gt;&gt;&gt;在请求处理之前进行调用（Controller方法调用之前）
&gt;&gt;&gt;MyInterceptor2&gt;&gt;&gt;&gt;&gt;&gt;&gt;请求处理之后进行调用，但是在视图被渲染之前（Controller方法调用之后）
&gt;&gt;&gt;MyInterceptor1&gt;&gt;&gt;&gt;&gt;&gt;&gt;请求处理之后进行调用，但是在视图被渲染之前（Controller方法调用之后）
&gt;&gt;&gt;MyInterceptor2&gt;&gt;&gt;&gt;&gt;&gt;&gt;在整个请求结束之后被调用，也就是在DispatcherServlet 渲染了对应的视图之后执行（主要是用于进行资源清理工作）
&gt;&gt;&gt;MyInterceptor1&gt;&gt;&gt;&gt;&gt;&gt;&gt;在整个请求结束之后被调用，也就是在DispatcherServlet 渲染了对应的视图之后执行（主要是用于进行资源清理工作）
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
</ul>
<p>根据输出可以了解拦截器链的执行顺序（具体原理介绍，大家找度娘一问便知）</p>
<p>最后强调一点：只有经过DispatcherServlet 的请求，才会走拦截器链，我们自定义的Servlet<br>请求是不会被拦截的，比如我们自定义的Servlet地址 <a href="http://localhost:8080/xs/myservlet" target="_blank" rel="noopener"> http://localhost:8080/xs/myservlet
</a> 是不会被拦截器拦截的。并且不管是属于哪个Servlet<br>只要复合过滤器的过滤规则，过滤器都会拦截。</p>
<p>最后说明下，我们上面用到的 WebMvcConfigurerAdapter 并非只是注册添加拦截器使用，其顾名思义是做Web配置用的，它还可以有很多其他作用<br>，通过下面截图便可以大概了解，具体每个方法都是干什么用的，留给大家自己研究（其实都大同小异也很简单）。<br><img src="https://img-blog.csdn.net/20160112092114468" alt="这里写图片描述"></p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">


    <div class="bdsharebuttonbox">
    <a href="#" class="bds_more" data-cmd="more">分享到：</a>
    <a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间">QQ空间</a>
    <a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博">新浪微博</a>
    <a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博">腾讯微博</a>
    <a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网">人人网</a>
    <a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信">微信</a>
</div>
<script>
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{"bdSize":16}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
</script>
<style>
    .bdshare_popup_box {
        border-radius: 4px;
        border: #e1e1e1 solid 1px;
    }
    .bdshare-button-style0-16 a,
    .bdshare-button-style0-16 .bds_more {
        padding-left: 20px;
        margin: 6px 10px 6px 0;
    }
    .bdshare_dialog_list a,
    .bdshare_popup_list a,
    .bdshare_popup_bottom a {
        font-family: 'Microsoft Yahei';
    }
    .bdshare_popup_top {
        display: none;
    }
    .bdshare_popup_bottom {
        height: auto;
        padding: 5px;
    }
</style>


</div>

            
    
        <a href="https://www.itchina.top/2018/04/20/Spring Boot 拦截器/#comments" id="sourceId::2018/04/20/Spring Boot 拦截器/" class="article-comment-link cy_cmt_count">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot 静态资源处理" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2018/04/20/Spring Boot 静态资源处理/">Spring Boot 静态资源处理</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2018/04/20/Spring Boot 静态资源处理/">
            <time datetime="2018-04-19T16:34:21.438Z" itemprop="datePublished">2018-04-20</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring/">Spring</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/spring/">spring</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p>Spring Boot 默认为我们提供了静态资源处理，使用 WebMvcAutoConfiguration 中的配置各种属性。</p>
<p>建议大家使用Spring Boot的默认配置方式，如果需要特殊处理的再通过配置进行修改。</p>
<p>如果想要自己完全控制WebMVC，就需要在@Configuration注解的配置类上增加@EnableWebMvc（@SpringBootApplicati<br>on 注解的程序入口类已经包含@Configuration），增加该注解以后WebMvcAutoConfiguration中配置就不会生效，你需要自己来配置<br>需要的每一项。这种情况下的配置还是要多看一下WebMvcAutoConfiguration类。</p>
<p>我们既然是快速使用Spring Boot，并不想过多的自己再重新配置。本文还是主要针对Spring Boot的默认处理方式，部分配置在application<br>配置文件中（.properties 或 .yml）</p>
<h2 id="默认资源映射"><a href="#默认资源映射" class="headerlink" title="默认资源映射"></a>默认资源映射</h2><p>我们在启动应用的时候，可以在控制台中看到如下信息：</p>
<pre><code>2016-01-08 09:29:30.362  INFO 24932 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-01-08 09:29:30.362  INFO 24932 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-01-08 09:29:30.437  INFO 24932 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
</ul>
<p>其中默认配置的 /<strong> 映射到 /static （或/public、/resources、/META-INF/resources）<br>其中默认配置的 /webjars/</strong> 映射到 classpath:/META-INF/resources/webjars/<br>PS：上面的 static、public、resources 等目录都在 classpath: 下面（如<br>src/main/resources/static）。</p>
<p>如果我按如下结构存放相同名称的图片，那么Spring Boot 读取图片的优先级是怎样的呢？<br>如下图：<br><img src="https://img-blog.csdn.net/20160112092328665" alt="这里写图片描述"></p>
<p>当我们访问地址 <a href="http://localhost:8080/fengjing.jpg" target="_blank" rel="noopener"> http://localhost:8080/fengjing.jpg
</a><br>的时候，显示哪张图片？这里博主可以直接告诉大家，优先级顺序为：META/resources &gt; resources &gt; static &gt; public<br>如果我们想访问pic2.jpg，请求地址 <a href="http://localhost:8080/img/pic2.jpg" target="_blank" rel="noopener"> http://localhost:8080/img/pic2.jpg
</a></p>
<h2 id="自定义资源映射"><a href="#自定义资源映射" class="headerlink" title="自定义资源映射"></a>自定义资源映射</h2><p>上面我们介绍了Spring Boot 的默认资源映射，一般够用了，那我们如何自定义目录？<br>这些资源都是打包在jar包中的，然后实际应用中，我们还有很多资源是在管理系统中动态维护的，并不可能在程序包中，对于这种随意指定目录的资源，如何访问？</p>
<h3 id="自定义目录"><a href="#自定义目录" class="headerlink" title="自定义目录"></a>自定义目录</h3><p>以增加 /myres/ _ <em> 映射到 classpath:/myres/</em> _ 为例的代码处理为：<br>实现类继承 WebMvcConfigurerAdapter 并重写方法 addResourceHandlers （对于<br>WebMvcConfigurerAdapter 上篇介绍拦截器的文章中已经有提到）</p>
<pre><code>package org.springboot.sample.config;

import org.springboot.sample.interceptor.MyInterceptor1;
import org.springboot.sample.interceptor.MyInterceptor2;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MyWebAppConfigurer 
        extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(&quot;/myres/**&quot;).addResourceLocations(&quot;classpath:/myres/&quot;);
        super.addResourceHandlers(registry);
    }

}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
</ul>
<p>访问myres 文件夹中的fengjing.jpg 图片的地址为 <a href="http://localhost:8080/myres/fengjing.jpg" target="_blank" rel="noopener"> http://localhost:8080/myres/fengjing.jpg
</a><br>这样使用代码的方式自定义目录映射，并不影响Spring Boot的默认映射，可以同时使用。</p>
<p>如果我们将/myres/ _ <em> 修改为 /</em> _ 与默认的相同时，则会覆盖系统的配置，可以多次使用 addResourceLocations<br>添加目录，优先级先添加的高于后添加的。</p>
<pre><code>// 访问myres根目录下的fengjing.jpg 的URL为 http://localhost:8080/fengjing.jpg （/** 会覆盖系统默认的配置）
// registry.addResourceHandler(&quot;/**&quot;).addResourceLocations(&quot;classpath:/myres/&quot;).addResourceLocations(&quot;classpath:/static/&quot;);
</code></pre><ul>
<li>1 </li>
<li>2 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
</ul>
<p>其中 addResourceLocations 的参数是动参，可以这样写 addResourceLocations(“classpath:/img1/”,<br>“classpath:/img2/”, “classpath:/img3/”);</p>
<h3 id="使用外部目录"><a href="#使用外部目录" class="headerlink" title="使用外部目录"></a>使用外部目录</h3><p>如果我们要指定一个绝对路径的文件夹（如 H:/myimgs/ ），则只需要使用 addResourceLocations 指定即可。</p>
<pre><code>// 可以直接使用addResourceLocations 指定磁盘绝对路径，同样可以配置多个位置，注意路径写法需要加上file:
registry.addResourceHandler(&quot;/myimgs/**&quot;).addResourceLocations(&quot;file:H:/myimgs/&quot;);
</code></pre><ul>
<li>1 </li>
<li>2 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
</ul>
<h3 id="通过配置文件配置"><a href="#通过配置文件配置" class="headerlink" title="通过配置文件配置"></a>通过配置文件配置</h3><p>上面是使用代码来定义静态资源的映射，其实Spring Boot也为我们提供了可以直接在<br>application.properties（或.yml）中配置的方法。<br>配置方法如下：</p>
<pre><code># 默认值为 /**
spring.mvc.static-path-pattern=
# 默认值为 classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/ 
spring.resources.static-locations=这里设置要指向的路径，多个使用英文逗号隔开，
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
</ul>
<p>使用 spring.mvc.static-path-pattern 可以重新定义pattern，如修改为 /myres/** ，则访问static<br>等目录下的fengjing.jpg文件应该为 <a href="http://localhost:8080/myres/fengjing.jpg" target="_blank" rel="noopener"> http://localhost:8080/myres/fengjing.jpg
</a> ，修改之前为 <a href="http://localhost:8080/fengjing.jpg" target="_blank" rel="noopener"><br>http://localhost:8080/fengjing.jpg </a><br>使用 spring.resources.static-locations 可以重新定义 pattern 所指向的路径，支持 classpath: 和<br>file: （上面已经做过说明）<br>注意 spring.mvc.static-path-pattern 只可以定义一个，目前不支持多个逗号分割的方式。</p>
<h2 id="页面中使用"><a href="#页面中使用" class="headerlink" title="页面中使用"></a>页面中使用</h2><p>上面几个例子中也已经说明了怎么访问静态资源，其实在页面中使用不管是jsp还是freemarker，并没有什么特殊之处，也我们平时开发web项目一样即可。<br>下面是我的index.jsp：</p>
<pre><code>&lt;body&gt;
    &lt;img alt=&quot;读取默认配置中的图片&quot; src=&quot;${pageContext.request.contextPath }/pic.jpg&quot;&gt;
    &lt;br/&gt;
    &lt;img alt=&quot;读取自定义配置myres中的图片&quot; src=&quot;${pageContext.request.contextPath }/myres/fengjing.jpg&quot;&gt;
&lt;/body&gt;
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
</ul>
<h2 id="使用webjars"><a href="#使用webjars" class="headerlink" title="使用webjars"></a>使用webjars</h2><p>先说一下什么是webjars？我们在Web开发中，前端页面中用了越来越多的JS或CSS，如 <a href="http://lib.csdn.net/base/22" target="_blank" rel="noopener"> jQuery
</a> 等等，平时我们是将这些Web资源拷贝到 <a href="http://lib.csdn.net/base/17" target="_blank" rel="noopener"> Java
</a> 的目录下，这种通过人工方式拷贝可能会产生版本误差，拷贝版本错误，前端页面就无法正确展示。<br>WebJars 就是为了解决这种问题衍生的，将这些Web前端资源打包成Java的Jar包，然后借助Maven这些依赖库的管理，保证这些Web资源版本唯一性。</p>
<p>WebJars 就是将js, css 等资源文件放到 classpath:/META-INF/resources/webjars/ 中，然后打包成jar<br>发布到maven仓库中。</p>
<h3 id="简单应用"><a href="#简单应用" class="headerlink" title="简单应用"></a>简单应用</h3><p>以jQuery为例，文件存放结构为：</p>
<pre><code>META-INF/resources/webjars/jquery/2.1.4/jquery.js
META-INF/resources/webjars/jquery/2.1.4/jquery.min.js
META-INF/resources/webjars/jquery/2.1.4/jquery.min.map
META-INF/resources/webjars/jquery/2.1.4/webjars-requirejs.js
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
</ul>
<p>Spring Boot 默认将 /webjars/** 映射到 classpath:/META-INF/resources/webjars/<br>，结合我们上面讲到的访问资源的规则，便可以得知我们在JSP页面中引入jquery.js的方法为：</p>
<pre><code>&lt;script type=&quot;text/javascript&quot; src=&quot;${pageContext.request.contextPath }/webjars/jquery/2.1.4/jquery.js&quot;&gt;&lt;/script&gt;
</code></pre><ul>
<li>1 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
</ul>
<p>想实现这样，我们只需要在pom.xml 文件中添加jquery的webjars 依赖即可，如下：</p>
<pre><code>&lt;dependency&gt;
    &lt;groupId&gt;org.webjars&lt;/groupId&gt;
    &lt;artifactId&gt;jquery&lt;/artifactId&gt;
    &lt;version&gt;2.1.4&lt;/version&gt;
&lt;/dependency&gt;
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
</ul>
<h3 id="版本号统一管理"><a href="#版本号统一管理" class="headerlink" title="版本号统一管理"></a>版本号统一管理</h3><p>但是我们实际开发中，可能会遇到升级版本号的情况，如果我们有100多个页面，几乎每个页面上都有按上面引入jquery.js<br>那么我们要把版本号更换为3.0.0，一个一个替换显然不是最好的办法。<br>如何来解决？按如下方法处理即可。</p>
<p>首先在pom.xml 中添加依赖：</p>
<pre><code>&lt;dependency&gt;
    &lt;groupId&gt;org.webjars&lt;/groupId&gt;
    &lt;artifactId&gt;webjars-locator&lt;/artifactId&gt;
&lt;/dependency&gt;
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
</ul>
<p>然后增加一个WebJarsController：</p>
<pre><code>package org.springboot.sample.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.HandlerMapping;
import org.webjars.WebJarAssetLocator;

/**
 * 处理WebJars，自动读取版本号
 *
 * @author   单红宇(365384722)
 * @myblog  http://blog.csdn.net/catoop/
 * @create    2016年1月8日
 */
@Controller
public class WebJarsController {

     private final WebJarAssetLocator assetLocator = new WebJarAssetLocator();

    @ResponseBody
    @RequestMapping(&quot;/webjarslocator/{webjar}/**&quot;)
    public ResponseEntity&lt;Object&gt; locateWebjarAsset(@PathVariable String webjar, HttpServletRequest request) {
        try {
            String mvcPrefix = &quot;/webjarslocator/&quot; + webjar + &quot;/&quot;; // This prefix must match the mapping path!
            String mvcPath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
            String fullPath = assetLocator.getFullPath(webjar, mvcPath.substring(mvcPrefix.length()));
            return new ResponseEntity&lt;&gt;(new ClassPathResource(fullPath), HttpStatus.OK);
        } catch (Exception e) {
            return new ResponseEntity&lt;&gt;(HttpStatus.NOT_FOUND);
        }
    }
}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
<li>40 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
<li>40 </li>
</ul>
<p>最后在页面中使用的方式：</p>
<pre><code>&lt;script type=&quot;text/javascript&quot; src=&quot;${pageContext.request.contextPath }/webjarslocator/jquery/jquery.js&quot;&gt;&lt;/script&gt;
</code></pre><ul>
<li>1 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
</ul>
<h2 id="静态资源版本管理"><a href="#静态资源版本管理" class="headerlink" title="静态资源版本管理"></a>静态资源版本管理</h2><p>Spring 默认提供了静态资源版本映射的支持。<br>当我们的资源内容发生改变时，由于浏览器缓存，用户本地的资源还是旧资源，为了防止这种情况发生导致的问题。我们可能会选择在资源文件后面加上参数“版本号”或其他方<br>式。</p>
<p>使用版本号参数，如：</p>
<pre><code>&lt;script type=&quot;text/javascript&quot; src=&quot;${pageContext.request.contextPath }/js/common.js?v=1.0.1&quot;&gt;&lt;/script&gt;
</code></pre><ul>
<li>1 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
</ul>
<p>使用这种方式，当我们文件修改后，手工修改版本号来达到URL文件不被浏览器缓存的目的。同样也存在很多文件都需要修改的问题。或者有的人会增加时间戳的方式，这样我<br>认为是最不可取的，每次浏览器都要请求为服务器增加了不必要的压力。</p>
<p>然而Spring在解决这种问题方面，提供了2种解决方式。<br>_ <em> 资源名称md5方式 </em> _<br>1. 修改 application.properties 配置文件（或.yml）</p>
<pre><code>spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
</code></pre><ul>
<li>1 </li>
<li>2 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
</ul>
<p>所有 /** 请求的静态资源都会被处理。</p>
<ol>
<li>创建 ResourceUrlProviderController 文件 </li>
</ol>
<pre><code>package org.springboot.sample.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.servlet.resource.ResourceUrlProvider;

/**
 * 处理静态资源URL
 *
 * @author 单红宇(365384722)
 * @myblog http://blog.csdn.net/catoop/
 * @create 2016年1月8日
 */
@ControllerAdvice
public class ResourceUrlProviderController {

    @Autowired
    private ResourceUrlProvider resourceUrlProvider;

    @ModelAttribute(&quot;urls&quot;)
    public ResourceUrlProvider urls() {
        return this.resourceUrlProvider;
    }
}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
</ul>
<ol>
<li>在页面中使用的写法 </li>
</ol>
<pre><code>&lt;script type=&quot;text/javascript&quot; src=&quot;${pageContext.request.contextPath }${urls.getForLookupPath(&apos;/js/common.js&apos;) }&quot;&gt;&lt;/script&gt;
</code></pre><ul>
<li>1 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
</ul>
<p>当我们访问页面后，HTML中实际生成的代码为：</p>
<pre><code>&lt;script type=&quot;text/javascript&quot; src=&quot;/myspringboot/js/common-c6b7da8fffc9be141b48c073e39c7340.js&quot;&gt;&lt;/script&gt;
</code></pre><ul>
<li>1 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
</ul>
<p>其中 /myspringboot 为我这个项目的 contextPath</p>
<p>_ <em> 资源版本号方式 </em> _<br>该方式本人觉得并无多大意义，也不做详细说明，这是对所有资源的统一版本控制，不像上面一个md5是针对文件的。<br>除了在 application.properties（或.yml）中的配置有所区别，页面使用和md5的一样。</p>
<pre><code>spring.resources.chain.strategy.fixed.enabled=true
spring.resources.chain.strategy.fixed.paths=/js/**,/v1.0.0/**
spring.resources.chain.strategy.fixed.version=v1.0.0
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
</ul>
<p>这样配置后，以上面 common.js 为例，实际页面中生成的HTML代码为：</p>
<pre><code>&lt;script type=&quot;text/javascript&quot; src=&quot;/myspringboot/v1.0.0/js/common.js&quot;&gt;&lt;/script&gt;
</code></pre><ul>
<li>1 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
</ul>
<p>_ <em> md5与版本号方式的处理原理 </em> _<br>页面中首先会调用urls.getForLookupPath方法，返回一个/v1.0.0/js/common.js或/css/common-<br>c6b7da8fffc9be141b48c073e39c7340.js<br>然后浏览器发起请求。<br>当请求的地址为md5方式时，会尝试url中的文件名中是否包含-，如果包含会去掉后面这部分，然后去映射的目录（如/static/）查找/js/common.j<br>s文件，如果能找到就返回。</p>
<p>当请求的地址为版本号方式时，会在url中判断是否存在/v1.0.0 ，如果存在，则先从URL中把 /v1.0.0<br>去掉，然后再去映射目录查找对应文件，找到就返回。</p>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>有这么多方式来管理我们的资源文件，然而在实际应用中虽然也都有可能用到（存在就有存在的道理嘛），但是凭借个人经验来说。<br>1. 我们使用第三方的库时，建议使用webjars的方式，通过动态版本号（webjars-locator<br>的方式）来使用（因为第三方库在项目开发中变动频率很小，即便是变动也是版本号的修改）。<br>2. 我们使用自己存放在静态资源映射目录中的资源的时候，建议使用md5 资源文件名的方式来使用（项目开发中一些css、js文件会经常修改）。<br>3. 项目素材文件建议放到 classpath:/static<br>（或其他）目录中，打包在项目中，通过CMS维护的一些图片和资源，我们使用配置引用到具体的磁盘绝对路径来使用。<br>4. 注意使用md5文件名方式的时候，Spring 是有缓存机制的，也就是说，在服务不重启的情况下，你去变动修改这些资源文件，其文件名的md5值并不会改变<br>，只有重启服务再次访问才会生效。如果需要每次都获取实际文件的md5值，需要重写相关类来实现，我们不建议这样做，因为一直去计算文件md5值是需要性能代价的。</p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">


    <div class="bdsharebuttonbox">
    <a href="#" class="bds_more" data-cmd="more">分享到：</a>
    <a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间">QQ空间</a>
    <a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博">新浪微博</a>
    <a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博">腾讯微博</a>
    <a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网">人人网</a>
    <a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信">微信</a>
</div>
<script>
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{"bdSize":16}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
</script>
<style>
    .bdshare_popup_box {
        border-radius: 4px;
        border: #e1e1e1 solid 1px;
    }
    .bdshare-button-style0-16 a,
    .bdshare-button-style0-16 .bds_more {
        padding-left: 20px;
        margin: 6px 10px 6px 0;
    }
    .bdshare_dialog_list a,
    .bdshare_popup_list a,
    .bdshare_popup_bottom a {
        font-family: 'Microsoft Yahei';
    }
    .bdshare_popup_top {
        display: none;
    }
    .bdshare_popup_bottom {
        height: auto;
        padding: 5px;
    }
</style>


</div>

            
    
        <a href="https://www.itchina.top/2018/04/20/Spring Boot 静态资源处理/#comments" id="sourceId::2018/04/20/Spring Boot 静态资源处理/" class="article-comment-link cy_cmt_count">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot 环境变量读取 和 属性对象的绑定" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2018/04/20/Spring Boot 环境变量读取 和 属性对象的绑定/">Spring Boot 环境变量读取 和 属性对象的绑定</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2018/04/20/Spring Boot 环境变量读取 和 属性对象的绑定/">
            <time datetime="2018-04-19T16:34:21.437Z" itemprop="datePublished">2018-04-20</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring/">Spring</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/spring/">spring</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p>凡是被Spring管理的类，实现接口 EnvironmentAware 重写方法 setEnvironment<br>可以在工程启动时，获取到系统环境变量和application配置文件中的变量。<br>如：</p>
<pre><code>@Configuration
public class MyWebAppConfigurer implements EnvironmentAware
        {
    private static final Logger logger = LoggerFactory.getLogger(MyWebAppConfigurer.class);

    private RelaxedPropertyResolver propertyResolver;

    @Value(&quot;${spring.datasource.url}&quot;)
    private String myUrl;

    /**
     * 这个方法只是测试实现EnvironmentAware接口，读取环境变量的方法。
     */
    @Override
    public void setEnvironment(Environment env) {
        logger.info(env.getProperty(&quot;JAVA_HOME&quot;));
        logger.info(myUrl);
        String str = env.getProperty(&quot;spring.datasource.url&quot;);
        logger.info(str);
        propertyResolver = new RelaxedPropertyResolver(env, &quot;spring.datasource.&quot;);
        String url = propertyResolver.getProperty(&quot;url&quot;);
        logger.info(url);
    }
}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
</ul>
<p>@Controller @Service 等被Spring管理的类都支持，注意重写的方法 setEnvironment 是在系统启动的时候被执行。<br>或者如下Controller：</p>
<pre><code>@Controller
public class PageController implements EnvironmentAware{

    @Override
    public void setEnvironment(Environment environment) {
        String s = environment.getProperty(&quot;JAVA_HOME&quot;);
        System.out.println(s);
    }
}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
</ul>
<p>我们还可以通过@ConfigurationProperties 读取application属性配置文件中的属性。</p>
<pre><code>@Configuration
@ConditionalOnClass(Mongo.class)
@EnableConfigurationProperties(MongoProperties.class)
public class MongoAutoConfiguration {

    @Autowired
    private MongoProperties properties; 

}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>@ConditionOnClass表明该@Configuration仅仅在一定条件下才会被加载，这里的条件是Mongo.class位于类路径上 </li>
<li>@EnableConfigurationProperties将Spring Boot的配置文件（application.properties）中的spring.data.mongodb.*属性映射为MongoProperties并注入到MongoAutoConfiguration中。 </li>
<li>@ConditionalOnMissingBean说明Spring Boot仅仅在当前上下文中不存在Mongo对象时，才会实例化一个Bean。这个逻辑也体现了Spring Boot的另外一个特性——自定义的Bean优先于框架的默认配置，我们如果显式的在业务代码中定义了一个Mongo对象，那么Spring Boot就不再创建。 </li>
</ul>
<pre><code>@ConfigurationProperties(prefix = &quot;spring.data.mongodb&quot;)
public class MongoProperties {

    private String host;
    private int port = DBPort.PORT;
    private String uri = &quot;mongodb://localhost/test&quot;;
    private String database;

    // ... getters/ setters omitted
} 
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
</ul>
<p>它就是以spring.data.mongodb作为前缀的属性，然后通过名字直接映射为对象的属性，同时还包含了一些默认值。如果不配置，那么mongo.uri就<br>是mongodb://localhost/test。</p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">


    <div class="bdsharebuttonbox">
    <a href="#" class="bds_more" data-cmd="more">分享到：</a>
    <a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间">QQ空间</a>
    <a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博">新浪微博</a>
    <a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博">腾讯微博</a>
    <a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网">人人网</a>
    <a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信">微信</a>
</div>
<script>
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{"bdSize":16}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
</script>
<style>
    .bdshare_popup_box {
        border-radius: 4px;
        border: #e1e1e1 solid 1px;
    }
    .bdshare-button-style0-16 a,
    .bdshare-button-style0-16 .bds_more {
        padding-left: 20px;
        margin: 6px 10px 6px 0;
    }
    .bdshare_dialog_list a,
    .bdshare_popup_list a,
    .bdshare_popup_bottom a {
        font-family: 'Microsoft Yahei';
    }
    .bdshare_popup_top {
        display: none;
    }
    .bdshare_popup_bottom {
        height: auto;
        padding: 5px;
    }
</style>


</div>

            
    
        <a href="https://www.itchina.top/2018/04/20/Spring Boot 环境变量读取 和 属性对象的绑定/#comments" id="sourceId::2018/04/20/Spring Boot 环境变量读取 和 属性对象的绑定/" class="article-comment-link cy_cmt_count">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot 集成Shiro和CAS" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2018/04/20/Spring Boot 集成Shiro和CAS/">Spring Boot 集成Shiro和CAS</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2018/04/20/Spring Boot 集成Shiro和CAS/">
            <time datetime="2018-04-19T16:34:21.437Z" itemprop="datePublished">2018-04-20</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring/">Spring</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/cas/">cas</a>, <a class="tag-link" href="/tags/shiro/">shiro</a>, <a class="tag-link" href="/tags/spring/">spring</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p>请大家在看本文之前，先了解如下知识点：<br>1、Shiro 是什么？怎么用？<br>2、Cas 是什么？怎么用？<br>3、最好有Spring基础</p>
<p>可以先看看这两篇文章，按照这2篇文章的内容做一遍：<br><a href="http://blog.csdn.net/catoop/article/details/50520958" target="_blank" rel="noopener"> Spring Boot Shiro 权限管理
</a><br><a href="http://blog.csdn.net/catoop/article/details/50530364" target="_blank" rel="noopener"> CAS单点登录 </a></p>
<p>首先看一下下面这张图：<br>第一个流程是单纯使用Shiro的流程。<br>第二个流程是单纯使用Cas的流程。<br>第三个图是Shiro集成Cas后的流程。</p>
<p>【流程图高清图连接： <a href="https://img-
blog.csdn.net/20160117224937078" target="_blank" rel="noopener"> https://img-blog.csdn.net/20160117224937078 </a> 】</p>
<p><img src="https://img-blog.csdn.net/20160117224937078" alt="流程图"></p>
<p>PS：流程图急急忙忙画的，整体上应该没有什么问题，具体细节问题还请大家留言指正。</p>
<p>如果你只是打算用到你的Spring Boot项目中，那么看着如下配置完成便可。<br>如果你想进一步了解其中的细节，还是建议大家单独配置Shiro、单独配置Cas，看看官方相关文档。<br>Shiro在1.2版本开始提供了对cas的集成，按下面添加依赖到pom.xml中：</p>
<pre><code>&lt;!--Apache Shiro所需的jar包 --&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.apache.shiro&lt;/groupId&gt;
    &lt;artifactId&gt;shiro-spring&lt;/artifactId&gt;
    &lt;version&gt;1.2.4&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;  
    &lt;groupId&gt;org.apache.shiro&lt;/groupId&gt;  
    &lt;artifactId&gt;shiro-ehcache&lt;/artifactId&gt;  
    &lt;version&gt;1.2.4&lt;/version&gt;  
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.apache.shiro&lt;/groupId&gt;
    &lt;artifactId&gt;shiro-cas&lt;/artifactId&gt;
    &lt;version&gt;1.2.4&lt;/version&gt;
&lt;/dependency&gt;
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
</ul>
<p>shiro-cas 依赖 shiro-web，shiro-web 依赖 shiro-core，所以添加shiro-cas后shiro-web<br>.jar和shiro-core.jar会自动被引用。<br>cas被shiro集成后，其原理就是shiro将casFilter加入到shiroFilter的filterChain中。</p>
<p>在SpringBoot工程中创建ShiroCasConfiguration. <a href="http://lib.csdn.net/base/17" target="_blank" rel="noopener"> Java </a></p>
<pre><code>package org.springboot.sample.config;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.cas.CasFilter;
import org.apache.shiro.cas.CasSubjectFactory;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springboot.sample.dao.IScoreDao;
import org.springboot.sample.security.MyShiroCasRealm;
import org.springboot.sample.service.StudentService;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;

/**
 * Shiro集成Cas配置
 *
 * @author   单红宇(365384722)
 * @myblog  http://blog.csdn.net/catoop/
 * @create    2016年1月17日
 */
@Configuration
public class ShiroCasConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(ShiroCasConfiguration.class);

    // CasServerUrlPrefix
    public static final String casServerUrlPrefix = &quot;https://localhost:8443/cas&quot;;
    // Cas登录页面地址
    public static final String casLoginUrl = casServerUrlPrefix + &quot;/login&quot;;
    // Cas登出页面地址
    public static final String casLogoutUrl = casServerUrlPrefix + &quot;/logout&quot;;
    // 当前工程对外提供的服务地址
    public static final String shiroServerUrlPrefix = &quot;http://localhost:9090/myspringboot&quot;;
    // casFilter UrlPattern
    public static final String casFilterUrlPattern = &quot;/shiro-cas&quot;;
    // 登录地址
    public static final String loginUrl = casLoginUrl + &quot;?service=&quot; + shiroServerUrlPrefix + casFilterUrlPattern;

    @Bean
    public EhCacheManager getEhCacheManager() {  
        EhCacheManager em = new EhCacheManager();  
        em.setCacheManagerConfigFile(&quot;classpath:ehcache-shiro.xml&quot;);  
        return em;  
    }  

    @Bean(name = &quot;myShiroCasRealm&quot;)
    public MyShiroCasRealm myShiroCasRealm(EhCacheManager cacheManager) {  
        MyShiroCasRealm realm = new MyShiroCasRealm(); 
        realm.setCacheManager(cacheManager);
        return realm;
    } 

    /**
     * 注册DelegatingFilterProxy（Shiro）
     *
     * @param dispatcherServlet
     * @return
     * @author SHANHY
     * @create  2016年1月13日
     */
    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new DelegatingFilterProxy(&quot;shiroFilter&quot;));
        //  该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理  
        filterRegistration.addInitParameter(&quot;targetFilterLifecycle&quot;, &quot;true&quot;);
        filterRegistration.setEnabled(true);
        filterRegistration.addUrlPatterns(&quot;/*&quot;);
        return filterRegistration;
    }

    @Bean(name = &quot;lifecycleBeanPostProcessor&quot;)
    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
        daap.setProxyTargetClass(true);
        return daap;
    }

    @Bean(name = &quot;securityManager&quot;)
    public DefaultWebSecurityManager getDefaultWebSecurityManager(MyShiroCasRealm myShiroCasRealm) {
        DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
        dwsm.setRealm(myShiroCasRealm);
//      &lt;!-- 用户授权/认证信息Cache, 采用EhCache 缓存 --&gt; 
        dwsm.setCacheManager(getEhCacheManager());
        // 指定 SubjectFactory
        dwsm.setSubjectFactory(new CasSubjectFactory());
        return dwsm;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
        aasa.setSecurityManager(securityManager);
        return aasa;
    }

    /**
     * 加载shiroFilter权限控制规则（从数据库读取然后配置）
     *
     * @author SHANHY
     * @create  2016年1月14日
     */
    private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean, StudentService stuService, IScoreDao scoreDao){
        /////////////////////// 下面这些规则配置最好配置到配置文件中 ///////////////////////
        Map&lt;String, String&gt; filterChainDefinitionMap = new LinkedHashMap&lt;String, String&gt;();

        filterChainDefinitionMap.put(casFilterUrlPattern, &quot;casFilter&quot;);// shiro集成cas后，首先添加该规则

        // authc：该过滤器下的页面必须验证后才能访问，它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter
        filterChainDefinitionMap.put(&quot;/user&quot;, &quot;authc&quot;);// 这里为了测试，只限制/user，实际开发中请修改为具体拦截的请求规则
        // anon：它对应的过滤器里面是空的,什么都没做
        logger.info(&quot;##################从数据库读取权限规则，加载到shiroFilter中##################&quot;);
        filterChainDefinitionMap.put(&quot;/user/edit/**&quot;, &quot;authc,perms[user:edit]&quot;);// 这里为了测试，固定写死的值，也可以从数据库或其他配置中读取

        filterChainDefinitionMap.put(&quot;/login&quot;, &quot;anon&quot;);
        filterChainDefinitionMap.put(&quot;/**&quot;, &quot;anon&quot;);//anon 可以理解为不拦截

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    }

    /**
     * CAS过滤器
     *
     * @return
     * @author SHANHY
     * @create  2016年1月17日
     */
    @Bean(name = &quot;casFilter&quot;)
    public CasFilter getCasFilter() {
        CasFilter casFilter = new CasFilter();
        casFilter.setName(&quot;casFilter&quot;);
        casFilter.setEnabled(true);
        // 登录失败后跳转的URL，也就是 Shiro 执行 CasRealm 的 doGetAuthenticationInfo 方法向CasServer验证tiket
        casFilter.setFailureUrl(loginUrl);// 我们选择认证失败后再打开登录页面
        return casFilter;
    }

    /**
     * ShiroFilter&lt;br/&gt;
     * 注意这里参数中的 StudentService 和 IScoreDao 只是一个例子，因为我们在这里可以用这样的方式获取到相关访问数据库的对象，
     * 然后读取数据库相关配置，配置到 shiroFilterFactoryBean 的访问规则中。实际项目中，请使用自己的Service来处理业务逻辑。
     *
     * @param myShiroCasRealm
     * @param stuService
     * @param scoreDao
     * @return
     * @author SHANHY
     * @create  2016年1月14日
     */
    @Bean(name = &quot;shiroFilter&quot;)
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager, CasFilter casFilter, StudentService stuService, IScoreDao scoreDao) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 必须设置 SecurityManager  
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 如果不设置默认会自动寻找Web工程根目录下的&quot;/login.jsp&quot;页面
        shiroFilterFactoryBean.setLoginUrl(loginUrl);
        // 登录成功后要跳转的连接
        shiroFilterFactoryBean.setSuccessUrl(&quot;/user&quot;);
        shiroFilterFactoryBean.setUnauthorizedUrl(&quot;/403&quot;);
        // 添加casFilter到shiroFilter中
        Map&lt;String, Filter&gt; filters = new HashMap&lt;&gt;();
        filters.put(&quot;casFilter&quot;, casFilter);
        shiroFilterFactoryBean.setFilters(filters);

        loadShiroFilterChain(shiroFilterFactoryBean, stuService, scoreDao);
        return shiroFilterFactoryBean;
    }

}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
<li>40 </li>
<li>41 </li>
<li>42 </li>
<li>43 </li>
<li>44 </li>
<li>45 </li>
<li>46 </li>
<li>47 </li>
<li>48 </li>
<li>49 </li>
<li>50 </li>
<li>51 </li>
<li>52 </li>
<li>53 </li>
<li>54 </li>
<li>55 </li>
<li>56 </li>
<li>57 </li>
<li>58 </li>
<li>59 </li>
<li>60 </li>
<li>61 </li>
<li>62 </li>
<li>63 </li>
<li>64 </li>
<li>65 </li>
<li>66 </li>
<li>67 </li>
<li>68 </li>
<li>69 </li>
<li>70 </li>
<li>71 </li>
<li>72 </li>
<li>73 </li>
<li>74 </li>
<li>75 </li>
<li>76 </li>
<li>77 </li>
<li>78 </li>
<li>79 </li>
<li>80 </li>
<li>81 </li>
<li>82 </li>
<li>83 </li>
<li>84 </li>
<li>85 </li>
<li>86 </li>
<li>87 </li>
<li>88 </li>
<li>89 </li>
<li>90 </li>
<li>91 </li>
<li>92 </li>
<li>93 </li>
<li>94 </li>
<li>95 </li>
<li>96 </li>
<li>97 </li>
<li>98 </li>
<li>99 </li>
<li>100 </li>
<li>101 </li>
<li>102 </li>
<li>103 </li>
<li>104 </li>
<li>105 </li>
<li>106 </li>
<li>107 </li>
<li>108 </li>
<li>109 </li>
<li>110 </li>
<li>111 </li>
<li>112 </li>
<li>113 </li>
<li>114 </li>
<li>115 </li>
<li>116 </li>
<li>117 </li>
<li>118 </li>
<li>119 </li>
<li>120 </li>
<li>121 </li>
<li>122 </li>
<li>123 </li>
<li>124 </li>
<li>125 </li>
<li>126 </li>
<li>127 </li>
<li>128 </li>
<li>129 </li>
<li>130 </li>
<li>131 </li>
<li>132 </li>
<li>133 </li>
<li>134 </li>
<li>135 </li>
<li>136 </li>
<li>137 </li>
<li>138 </li>
<li>139 </li>
<li>140 </li>
<li>141 </li>
<li>142 </li>
<li>143 </li>
<li>144 </li>
<li>145 </li>
<li>146 </li>
<li>147 </li>
<li>148 </li>
<li>149 </li>
<li>150 </li>
<li>151 </li>
<li>152 </li>
<li>153 </li>
<li>154 </li>
<li>155 </li>
<li>156 </li>
<li>157 </li>
<li>158 </li>
<li>159 </li>
<li>160 </li>
<li>161 </li>
<li>162 </li>
<li>163 </li>
<li>164 </li>
<li>165 </li>
<li>166 </li>
<li>167 </li>
<li>168 </li>
<li>169 </li>
<li>170 </li>
<li>171 </li>
<li>172 </li>
<li>173 </li>
<li>174 </li>
<li>175 </li>
<li>176 </li>
<li>177 </li>
<li>178 </li>
<li>179 </li>
<li>180 </li>
<li>181 </li>
<li>182 </li>
<li>183 </li>
<li>184 </li>
<li>185 </li>
<li>186 </li>
<li>187 </li>
<li>188 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
<li>40 </li>
<li>41 </li>
<li>42 </li>
<li>43 </li>
<li>44 </li>
<li>45 </li>
<li>46 </li>
<li>47 </li>
<li>48 </li>
<li>49 </li>
<li>50 </li>
<li>51 </li>
<li>52 </li>
<li>53 </li>
<li>54 </li>
<li>55 </li>
<li>56 </li>
<li>57 </li>
<li>58 </li>
<li>59 </li>
<li>60 </li>
<li>61 </li>
<li>62 </li>
<li>63 </li>
<li>64 </li>
<li>65 </li>
<li>66 </li>
<li>67 </li>
<li>68 </li>
<li>69 </li>
<li>70 </li>
<li>71 </li>
<li>72 </li>
<li>73 </li>
<li>74 </li>
<li>75 </li>
<li>76 </li>
<li>77 </li>
<li>78 </li>
<li>79 </li>
<li>80 </li>
<li>81 </li>
<li>82 </li>
<li>83 </li>
<li>84 </li>
<li>85 </li>
<li>86 </li>
<li>87 </li>
<li>88 </li>
<li>89 </li>
<li>90 </li>
<li>91 </li>
<li>92 </li>
<li>93 </li>
<li>94 </li>
<li>95 </li>
<li>96 </li>
<li>97 </li>
<li>98 </li>
<li>99 </li>
<li>100 </li>
<li>101 </li>
<li>102 </li>
<li>103 </li>
<li>104 </li>
<li>105 </li>
<li>106 </li>
<li>107 </li>
<li>108 </li>
<li>109 </li>
<li>110 </li>
<li>111 </li>
<li>112 </li>
<li>113 </li>
<li>114 </li>
<li>115 </li>
<li>116 </li>
<li>117 </li>
<li>118 </li>
<li>119 </li>
<li>120 </li>
<li>121 </li>
<li>122 </li>
<li>123 </li>
<li>124 </li>
<li>125 </li>
<li>126 </li>
<li>127 </li>
<li>128 </li>
<li>129 </li>
<li>130 </li>
<li>131 </li>
<li>132 </li>
<li>133 </li>
<li>134 </li>
<li>135 </li>
<li>136 </li>
<li>137 </li>
<li>138 </li>
<li>139 </li>
<li>140 </li>
<li>141 </li>
<li>142 </li>
<li>143 </li>
<li>144 </li>
<li>145 </li>
<li>146 </li>
<li>147 </li>
<li>148 </li>
<li>149 </li>
<li>150 </li>
<li>151 </li>
<li>152 </li>
<li>153 </li>
<li>154 </li>
<li>155 </li>
<li>156 </li>
<li>157 </li>
<li>158 </li>
<li>159 </li>
<li>160 </li>
<li>161 </li>
<li>162 </li>
<li>163 </li>
<li>164 </li>
<li>165 </li>
<li>166 </li>
<li>167 </li>
<li>168 </li>
<li>169 </li>
<li>170 </li>
<li>171 </li>
<li>172 </li>
<li>173 </li>
<li>174 </li>
<li>175 </li>
<li>176 </li>
<li>177 </li>
<li>178 </li>
<li>179 </li>
<li>180 </li>
<li>181 </li>
<li>182 </li>
<li>183 </li>
<li>184 </li>
<li>185 </li>
<li>186 </li>
<li>187 </li>
<li>188 </li>
</ul>
<p>创建权限认证的 MyShiroCasRealm.java</p>
<pre><code>package org.springboot.sample.security;

import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cas.CasRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springboot.sample.config.ShiroCasConfiguration;
import org.springboot.sample.dao.IUserDao;
import org.springboot.sample.entity.Role;
import org.springboot.sample.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

public class MyShiroCasRealm extends CasRealm{

    private static final Logger logger = LoggerFactory.getLogger(MyShiroCasRealm.class);

    @Autowired
    private IUserDao userDao; 

    @PostConstruct
    public void initProperty(){
//      setDefaultRoles(&quot;ROLE_USER&quot;);
        setCasServerUrlPrefix(ShiroCasConfiguration.casServerUrlPrefix);
        // 客户端回调地址
        setCasService(ShiroCasConfiguration.shiroServerUrlPrefix + ShiroCasConfiguration.casFilterUrlPattern);
    }

    /**
     * 权限认证，为当前登录的Subject授予角色和权限 
     * @see 经测试：本例中该方法的调用时机为需授权资源被访问时 
     * @see 经测试：并且每次访问需授权资源时都会执行该方法中的逻辑，这表明本例中默认并未启用AuthorizationCache 
     * @see 经测试：如果连续访问同一个URL（比如刷新），该方法不会被重复调用，Shiro有一个时间间隔（也就是cache时间，在ehcache-shiro.xml中配置），超过这个时间间隔再刷新页面，该方法会被执行
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        logger.info(&quot;##################执行Shiro权限认证##################&quot;);
        //获取当前登录输入的用户名，等价于(String) principalCollection.fromRealm(getName()).iterator().next();
        String loginName = (String)super.getAvailablePrincipal(principalCollection); 
        //到数据库查是否有此对象
        User user=userDao.findByName(loginName);// 实际项目中，这里可以根据实际情况做缓存，如果不做，Shiro自己也是有时间间隔机制，2分钟内不会重复执行该方法
        if(user!=null){
            //权限信息对象info,用来存放查出的用户的所有的角色（role）及权限（permission）
            SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
            //用户的角色集合
            info.setRoles(user.getRolesName());
            //用户的角色对应的所有权限，如果只使用角色定义访问权限，下面的四行可以不要
            List&lt;Role&gt; roleList=user.getRoleList();
            for (Role role : roleList) {
                info.addStringPermissions(role.getPermissionsName());
            }
            // 或者按下面这样添加
            //添加一个角色,不是配置意义上的添加,而是证明该用户拥有admin角色    
//            simpleAuthorInfo.addRole(&quot;admin&quot;);  
            //添加权限  
//            simpleAuthorInfo.addStringPermission(&quot;admin:manage&quot;);  
//            logger.info(&quot;已为用户[mike]赋予了[admin]角色和[admin:manage]权限&quot;);
            return info;
        }
        // 返回null的话，就会导致任何用户访问被拦截的请求时，都会自动跳转到unauthorizedUrl指定的地址
        return null;
    }

}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
<li>40 </li>
<li>41 </li>
<li>42 </li>
<li>43 </li>
<li>44 </li>
<li>45 </li>
<li>46 </li>
<li>47 </li>
<li>48 </li>
<li>49 </li>
<li>50 </li>
<li>51 </li>
<li>52 </li>
<li>53 </li>
<li>54 </li>
<li>55 </li>
<li>56 </li>
<li>57 </li>
<li>58 </li>
<li>59 </li>
<li>60 </li>
<li>61 </li>
<li>62 </li>
<li>63 </li>
<li>64 </li>
<li>65 </li>
<li>66 </li>
<li>67 </li>
<li>68 </li>
<li>69 </li>
<li>70 </li>
<li>71 </li>
<li>72 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
<li>40 </li>
<li>41 </li>
<li>42 </li>
<li>43 </li>
<li>44 </li>
<li>45 </li>
<li>46 </li>
<li>47 </li>
<li>48 </li>
<li>49 </li>
<li>50 </li>
<li>51 </li>
<li>52 </li>
<li>53 </li>
<li>54 </li>
<li>55 </li>
<li>56 </li>
<li>57 </li>
<li>58 </li>
<li>59 </li>
<li>60 </li>
<li>61 </li>
<li>62 </li>
<li>63 </li>
<li>64 </li>
<li>65 </li>
<li>66 </li>
<li>67 </li>
<li>68 </li>
<li>69 </li>
<li>70 </li>
<li>71 </li>
<li>72 </li>
</ul>
<p>在Controller中添加一个方法，用于将登录URL简单化，提供一个重定向功能</p>
<pre><code>    @RequestMapping(value=&quot;/login&quot;,method=RequestMethod.GET)
    public String loginForm(Model model){
        model.addAttribute(&quot;user&quot;, new User());
//      return &quot;login&quot;;
        return &quot;redirect:&quot; + ShiroCasConfiguration.loginUrl;
    }
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
</ul>
<p>本文主要是介绍如何在Spring Boot中集成Shiro+Cas，并非一个从零创建工程到整体完成的介绍。<br>上面贴出了2个主要的Java类，整个工程的其他所有代码没有任何与Shiro和Cas耦合的地方。如果需要jsp页面、Controller、实体类、连接 <a href="http://lib.csdn.net/base/14" target="_blank" rel="noopener"><br>数据库 </a> 测试数据等代码，可以先参考文章： <a href="http://blog.csdn.net/lsy0903/article/details/52910744" target="_blank" rel="noopener"><br>http://blog.csdn.net/lsy0903/article/details/52910744
</a> （建议先看这篇文章再看本文）</p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">


    <div class="bdsharebuttonbox">
    <a href="#" class="bds_more" data-cmd="more">分享到：</a>
    <a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间">QQ空间</a>
    <a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博">新浪微博</a>
    <a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博">腾讯微博</a>
    <a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网">人人网</a>
    <a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信">微信</a>
</div>
<script>
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{"bdSize":16}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
</script>
<style>
    .bdshare_popup_box {
        border-radius: 4px;
        border: #e1e1e1 solid 1px;
    }
    .bdshare-button-style0-16 a,
    .bdshare-button-style0-16 .bds_more {
        padding-left: 20px;
        margin: 6px 10px 6px 0;
    }
    .bdshare_dialog_list a,
    .bdshare_popup_list a,
    .bdshare_popup_bottom a {
        font-family: 'Microsoft Yahei';
    }
    .bdshare_popup_top {
        display: none;
    }
    .bdshare_popup_bottom {
        height: auto;
        padding: 5px;
    }
</style>


</div>

            
    
        <a href="https://www.itchina.top/2018/04/20/Spring Boot 集成Shiro和CAS/#comments" id="sourceId::2018/04/20/Spring Boot 集成Shiro和CAS/" class="article-comment-link cy_cmt_count">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot 过滤器、监听器" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2018/04/20/Spring Boot 过滤器、监听器/">Spring Boot 过滤器、监听器</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2018/04/20/Spring Boot 过滤器、监听器/">
            <time datetime="2018-04-19T16:34:21.436Z" itemprop="datePublished">2018-04-20</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring/">Spring</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/spring/">spring</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p>上一篇文章已经对定义Servlet 的方法进行了说明，过滤器（Filter）和 监听器（Listener）的注册方法和 Servlet<br>一样，不清楚的可以查看下上一篇文章： <a href="http://blog.csdn.net/lsy0903/article/details/52910612" target="_blank" rel="noopener"> http://blog.csdn.net/lsy0903/article/details/52910612
</a><br>本文将直接使用@WebFilter和@WebListener的方式，完成一个Filter 和一个 Listener。</p>
<p><strong> 过滤器（Filter）文件 </strong></p>
<p>MyFilter. <a href="http://lib.csdn.net/base/17" target="_blank" rel="noopener"> Java </a></p>
<pre><code>package org.springboot.sample.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

/**
 * 使用注解标注过滤器
 * @WebFilter将一个实现了javax.servlet.Filter接口的类定义为过滤器
 * 属性filterName声明过滤器的名称,可选
 * 属性urlPatterns指定要过滤 的URL模式,也可使用属性value来声明.(指定要过滤的URL模式是必选属性)
 * 
 * @author   单红宇(365384722)
 * @myblog  http://blog.csdn.net/catoop/
 * @create    2016年1月6日
 */
@WebFilter(filterName=&quot;myFilter&quot;,urlPatterns=&quot;/*&quot;)
public class MyFilter implements Filter {

    @Override
    public void destroy() {
        System.out.println(&quot;过滤器销毁&quot;);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println(&quot;执行过滤操作&quot;);
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig config) throws ServletException {
        System.out.println(&quot;过滤器初始化&quot;);
    }

}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
<li>40 </li>
<li>41 </li>
<li>42 </li>
<li>43 </li>
<li>44 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
<li>30 </li>
<li>31 </li>
<li>32 </li>
<li>33 </li>
<li>34 </li>
<li>35 </li>
<li>36 </li>
<li>37 </li>
<li>38 </li>
<li>39 </li>
<li>40 </li>
<li>41 </li>
<li>42 </li>
<li>43 </li>
<li>44 </li>
</ul>
<p><strong> ServletContext监听器（Listener）文件 </strong></p>
<p>MyServletContextListener.java</p>
<pre><code>package org.springboot.sample.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

/**
 * 使用@WebListener注解，实现ServletContextListener接口
 *
 * @author   单红宇(365384722)
 * @myblog  http://blog.csdn.net/catoop/
 * @create    2016年1月6日
 */
@WebListener
public class MyServletContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println(&quot;ServletContex初始化&quot;);
        System.out.println(sce.getServletContext().getServerInfo());
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println(&quot;ServletContex销毁&quot;);
    }

}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
<li>29 </li>
</ul>
<p><strong> ServletContext监听器（Listener）文件 </strong></p>
<p>MyHttpSessionListener.java</p>
<pre><code>package org.springboot.sample.listener;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * 监听Session的创建与销毁
 *
 * @author   单红宇(365384722)
 * @myblog  http://blog.csdn.net/catoop/
 * @create    2016年1月6日
 */
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println(&quot;Session 被创建&quot;);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println(&quot;ServletContex初始化&quot;);
    }

}
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
<li>4 </li>
<li>5 </li>
<li>6 </li>
<li>7 </li>
<li>8 </li>
<li>9 </li>
<li>10 </li>
<li>11 </li>
<li>12 </li>
<li>13 </li>
<li>14 </li>
<li>15 </li>
<li>16 </li>
<li>17 </li>
<li>18 </li>
<li>19 </li>
<li>20 </li>
<li>21 </li>
<li>22 </li>
<li>23 </li>
<li>24 </li>
<li>25 </li>
<li>26 </li>
<li>27 </li>
<li>28 </li>
</ul>
<p>注意不要忘记在 SpringBootSampleApplication.java 上添加 @ServletComponentScan 注解。</p>
<p>在启动的过程中我们会看到输出：</p>
<pre><code>ServletContex初始化
Apache Tomcat/8.0.30
过滤器初始化
</code></pre><ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
<li>3 </li>
</ul>
<p>服务启动后，随便访问一个页面，会看到输出：</p>
<pre><code>执行过滤操作
Session 被创建
</code></pre><ul>
<li>1 </li>
<li>2 </li>
</ul>
<p><img src="http://static.blog.csdn.net/images/save_snippets.png" alt=""></p>
<ul>
<li>1 </li>
<li>2 </li>
</ul>
<p>至于如何使用代码的方式注册Filter和Listener，请参考上一篇文章关键Servlet的介绍。不同的是需要使用<br>FilterRegistrationBean 和 ServletListenerRegistrationBean 这两个类。</p>
<p>最后上一张工程结构图：<br><img src="https://img-blog.csdn.net/20160112092021469" alt="这里写图片描述"></p>
<p>代码目前还没有一个警告 ^_^</p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">


    <div class="bdsharebuttonbox">
    <a href="#" class="bds_more" data-cmd="more">分享到：</a>
    <a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间">QQ空间</a>
    <a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博">新浪微博</a>
    <a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博">腾讯微博</a>
    <a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网">人人网</a>
    <a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信">微信</a>
</div>
<script>
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{"bdSize":16}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
</script>
<style>
    .bdshare_popup_box {
        border-radius: 4px;
        border: #e1e1e1 solid 1px;
    }
    .bdshare-button-style0-16 a,
    .bdshare-button-style0-16 .bds_more {
        padding-left: 20px;
        margin: 6px 10px 6px 0;
    }
    .bdshare_dialog_list a,
    .bdshare_popup_list a,
    .bdshare_popup_bottom a {
        font-family: 'Microsoft Yahei';
    }
    .bdshare_popup_top {
        display: none;
    }
    .bdshare_popup_bottom {
        height: auto;
        padding: 5px;
    }
</style>


</div>

            
    
        <a href="https://www.itchina.top/2018/04/20/Spring Boot 过滤器、监听器/#comments" id="sourceId::2018/04/20/Spring Boot 过滤器、监听器/" class="article-comment-link cy_cmt_count">评论</a>
    

        </footer>
    </div>
    
</article>



    <nav id="page-nav">
        <a class="extend prev" rel="prev" href="/">&laquo; 上一页</a><a class="page-number" href="/">1</a><span class="page-number current">2</span><a class="page-number" href="/page/3/">3</a><a class="page-number" href="/page/4/">4</a><span class="space">&hellip;</span><a class="page-number" href="/page/7/">7</a><a class="extend next" rel="next" href="/page/3/">下一页 &raquo;</a>
    </nav>
</section>
            
                
<aside id="sidebar">
   
        
    <div class="widget-wrap">
        <h3 class="widget-title">最新文章</h3>
        <div class="widget">
            <ul id="recent-post" class="no-thumbnail">
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/IDE/">IDE</a></p>
                            <p class="item-title"><a href="/2018/04/20/项目相关的CVS操作/" class="title">项目相关的CVS操作</a></p>
                            <p class="item-date"><time datetime="2018-04-19T16:34:21.467Z" itemprop="datePublished">2018-04-20</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/J2EE/">J2EE</a></p>
                            <p class="item-title"><a href="/2018/04/20/图片转换PDF文件/" class="title">图片转换PDF文件</a></p>
                            <p class="item-date"><time datetime="2018-04-19T16:34:21.449Z" itemprop="datePublished">2018-04-20</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/Spring/">Spring</a></p>
                            <p class="item-title"><a href="/2018/04/20/使用 Spring Data JPA 简化 JPA 开发/" class="title">使用 Spring Data JPA 简化 JPA 开发</a></p>
                            <p class="item-date"><time datetime="2018-04-19T16:34:21.448Z" itemprop="datePublished">2018-04-20</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"></p>
                            <p class="item-title"><a href="/2018/04/20/通过Ajax进行POST提交JSON类型的数据到SpringMVC Controller的方法/" class="title">通过Ajax进行POST提交JSON类型的数据到SpringMVC Controller的方法</a></p>
                            <p class="item-date"><time datetime="2018-04-19T16:34:21.448Z" itemprop="datePublished">2018-04-20</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"></p>
                            <p class="item-title"><a href="/2018/04/20/面试感悟----一名3年工作经验的程序员应该具备的技能/" class="title">面试感悟----一名3年工作经验的程序员应该具备的技能</a></p>
                            <p class="item-date"><time datetime="2018-04-19T16:34:21.447Z" itemprop="datePublished">2018-04-20</time></p>
                        </div>
                    </li>
                
            </ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">分类</h3>
        <div class="widget">
            <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/ActiveMQ/">ActiveMQ</a><span class="category-list-count">7</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/ExtJs/">ExtJs</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Git/">Git</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/IDE/">IDE</a><span class="category-list-count">4</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/J2EE/">J2EE</a><span class="category-list-count">7</span><ul class="category-list-child"><li class="category-list-item"><a class="category-list-link" href="/categories/J2EE/Spring/">Spring</a><span class="category-list-count">1</span></li></ul></li><li class="category-list-item"><a class="category-list-link" href="/categories/Linux/">Linux</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Redis/">Redis</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Spring/">Spring</a><span class="category-list-count">21</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/cnn图片数据处理、显示/">cnn图片数据处理、显示</a><span class="category-list-count">1</span><ul class="category-list-child"><li class="category-list-item"><a class="category-list-link" href="/categories/cnn图片数据处理、显示/python数据分析/">python数据分析</a><span class="category-list-count">1</span></li></ul></li><li class="category-list-item"><a class="category-list-link" href="/categories/web前端/">web前端</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/数据库/">数据库</a><span class="category-list-count">3</span><ul class="category-list-child"><li class="category-list-item"><a class="category-list-link" href="/categories/数据库/集群/">集群</a><span class="category-list-count">1</span></li></ul></li><li class="category-list-item"><a class="category-list-link" href="/categories/集群/">集群</a><span class="category-list-count">2</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">归档</h3>
        <div class="widget">
            <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/04/">四月 2018</a><span class="archive-list-count">65</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">标签</h3>
        <div class="widget">
            <ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/tags/Apache/">Apache</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Docker/">Docker</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Druid/">Druid</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/ImageToPDF/">ImageToPDF</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Logstash/">Logstash</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Spring-Boot/">Spring Boot</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/activemq/">activemq</a><span class="tag-list-count">7</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/ajax/">ajax</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/angular/">angular</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/cas/">cas</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/docker/">docker</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/exception/">exception</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/ext/">ext</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/extjs/">extjs</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/find/">find</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/git/">git</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/github/">github</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/ide/">ide</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/idea/">idea</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/java/">java</a><span class="tag-list-count">5</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/javascript/">javascript</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/jboss/">jboss</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/jmx/">jmx</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/jpa/">jpa</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/linux/">linux</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/lombok/">lombok</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/mvc/">mvc</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/mybatis/">mybatis</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/mysql/">mysql</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/nginx/">nginx</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/numpy/">numpy</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/seo/">seo</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/server/">server</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/shiro/">shiro</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/spring/">spring</a><span class="tag-list-count">17</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/spring-mvc/">spring mvc</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/spring-boo/">spring-boo</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/sql-server/">sql server</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/windows/">windows</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/zookeeper/">zookeeper</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/优化/">优化</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/分布式日志/">分布式日志</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/多线程/">多线程</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/工作/">工作</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/异常/">异常</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/异常处理/">异常处理</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/搜索引擎/">搜索引擎</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/数据分析/">数据分析</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/汉字转拼音/">汉字转拼音</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/版本控制系统/">版本控制系统</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/程序员/">程序员</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/经验/">经验</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/集群/">集群</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/面试/">面试</a><span class="tag-list-count">1</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">标签云</h3>
        <div class="widget tagcloud">
            <a href="/tags/Apache/" style="font-size: 10px;">Apache</a> <a href="/tags/Docker/" style="font-size: 10px;">Docker</a> <a href="/tags/Druid/" style="font-size: 10px;">Druid</a> <a href="/tags/ImageToPDF/" style="font-size: 10px;">ImageToPDF</a> <a href="/tags/Logstash/" style="font-size: 10px;">Logstash</a> <a href="/tags/Spring-Boot/" style="font-size: 10px;">Spring Boot</a> <a href="/tags/activemq/" style="font-size: 18px;">activemq</a> <a href="/tags/ajax/" style="font-size: 10px;">ajax</a> <a href="/tags/angular/" style="font-size: 10px;">angular</a> <a href="/tags/cas/" style="font-size: 10px;">cas</a> <a href="/tags/docker/" style="font-size: 10px;">docker</a> <a href="/tags/exception/" style="font-size: 10px;">exception</a> <a href="/tags/ext/" style="font-size: 14px;">ext</a> <a href="/tags/extjs/" style="font-size: 14px;">extjs</a> <a href="/tags/find/" style="font-size: 10px;">find</a> <a href="/tags/git/" style="font-size: 10px;">git</a> <a href="/tags/github/" style="font-size: 10px;">github</a> <a href="/tags/ide/" style="font-size: 12px;">ide</a> <a href="/tags/idea/" style="font-size: 10px;">idea</a> <a href="/tags/java/" style="font-size: 16px;">java</a> <a href="/tags/javascript/" style="font-size: 12px;">javascript</a> <a href="/tags/jboss/" style="font-size: 10px;">jboss</a> <a href="/tags/jmx/" style="font-size: 10px;">jmx</a> <a href="/tags/jpa/" style="font-size: 10px;">jpa</a> <a href="/tags/linux/" style="font-size: 14px;">linux</a> <a href="/tags/lombok/" style="font-size: 10px;">lombok</a> <a href="/tags/mvc/" style="font-size: 10px;">mvc</a> <a href="/tags/mybatis/" style="font-size: 10px;">mybatis</a> <a href="/tags/mysql/" style="font-size: 12px;">mysql</a> <a href="/tags/nginx/" style="font-size: 10px;">nginx</a> <a href="/tags/numpy/" style="font-size: 10px;">numpy</a> <a href="/tags/seo/" style="font-size: 10px;">seo</a> <a href="/tags/server/" style="font-size: 10px;">server</a> <a href="/tags/shiro/" style="font-size: 12px;">shiro</a> <a href="/tags/spring/" style="font-size: 20px;">spring</a> <a href="/tags/spring-mvc/" style="font-size: 10px;">spring mvc</a> <a href="/tags/spring-boo/" style="font-size: 10px;">spring-boo</a> <a href="/tags/sql-server/" style="font-size: 10px;">sql server</a> <a href="/tags/windows/" style="font-size: 10px;">windows</a> <a href="/tags/zookeeper/" style="font-size: 10px;">zookeeper</a> <a href="/tags/优化/" style="font-size: 12px;">优化</a> <a href="/tags/分布式日志/" style="font-size: 10px;">分布式日志</a> <a href="/tags/多线程/" style="font-size: 10px;">多线程</a> <a href="/tags/工作/" style="font-size: 10px;">工作</a> <a href="/tags/异常/" style="font-size: 10px;">异常</a> <a href="/tags/异常处理/" style="font-size: 10px;">异常处理</a> <a href="/tags/搜索引擎/" style="font-size: 12px;">搜索引擎</a> <a href="/tags/数据分析/" style="font-size: 10px;">数据分析</a> <a href="/tags/汉字转拼音/" style="font-size: 10px;">汉字转拼音</a> <a href="/tags/版本控制系统/" style="font-size: 10px;">版本控制系统</a> <a href="/tags/程序员/" style="font-size: 10px;">程序员</a> <a href="/tags/经验/" style="font-size: 10px;">经验</a> <a href="/tags/集群/" style="font-size: 10px;">集群</a> <a href="/tags/面试/" style="font-size: 10px;">面试</a>
        </div>
    </div>

    
        
    <div class="widget-wrap widget-list">
        <h3 class="widget-title">链接</h3>
        <div class="widget">
            <ul>
                
                    <li>
                        <a href="http://www.baidu.com">百度</a>
                    </li>
                
            </ul>
        </div>
    </div>


    
    <div id="toTop" class="fa fa-angle-up"></div>
</aside>

            
        </div>
        <!--google 底部广告 -->
<div style="width:100%;text-align: center;clear: both;margin-bottom: 20px;" class="hidden-xs">
    <script async src="http://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
    <!-- 博客footer上方的广告 -->
    <ins class="adsbygoogle"
         style="display:block"
         data-ad-client="ca-pub-8254913025324557"
         data-ad-slot="3369473724"
         data-ad-format="auto"></ins>
    <script>
        (adsbygoogle = window.adsbygoogle || []).push({});
    </script>
</div>
<footer id="footer">
    <div class="outer">
        <div id="footer-info" class="inner">
            &copy;2018 - 2018&nbsp; LErry Li &nbsp;版权所有<br>
			<a href="http://www.miitbeian.gov.cn">沪ICP备17054498号-3</a>
        </div>
    </div>
</footer>
        
    
    <script id="cy_cmt_num" src="https://changyan.sohu.com/upload/plugins/plugins.list.count.js?clientId=cytxPSIHr"></script>
    <script charset="utf-8" type="text/javascript" src="https://changyan.sohu.com/upload/changyan.js" ></script>
    <script type="text/javascript">
    window.changyan.api.config({
    appid: 'cytxPSIHr',
    conf: 'prod_3c92d05d8ba4377e48c5fe27c2159761'
    });
    </script>




    
        <script src="/libs/lightgallery/js/lightgallery.min.js"></script>
        <script src="/libs/lightgallery/js/lg-thumbnail.min.js"></script>
        <script src="/libs/lightgallery/js/lg-pager.min.js"></script>
        <script src="/libs/lightgallery/js/lg-autoplay.min.js"></script>
        <script src="/libs/lightgallery/js/lg-fullscreen.min.js"></script>
        <script src="/libs/lightgallery/js/lg-zoom.min.js"></script>
        <script src="/libs/lightgallery/js/lg-hash.min.js"></script>
        <script src="/libs/lightgallery/js/lg-share.min.js"></script>
        <script src="/libs/lightgallery/js/lg-video.min.js"></script>
    
    
        <script src="/libs/justified-gallery/jquery.justifiedGallery.min.js"></script>
    
    



<!-- Custom Scripts -->
<script src="/js/main.js"></script>

    </div>
</body>
</html>